import common = require("./action-bar-common");
import types = require("utils/types");
import enums = require("ui/enums");
import application = require("application");
import dts = require("ui/action-bar");
import view = require("ui/core/view");
import * as traceModule from "trace";
import * as utilsModule from "utils/utils";
import * as imageSourceModule from "image-source";
import style = require("ui/styling/style");

const R_ID_HOME = 0x0102002c;
const ACTION_ITEM_ID_OFFSET = 1000;

global.moduleMerge(common, exports);

var trace: typeof traceModule;
function ensureTrace() {
    if (!trace) {
        trace = require("trace");
    }
}

var utils: typeof utilsModule;
function ensureUtils() {
    if (!utils) {
        utils = require("utils/utils");
    }
}

var imageSource: typeof imageSourceModule;
function ensureImageSource() {
    if (!imageSource) {
        imageSource = require("image-source");
    }
}

var actionItemIdGenerator = ACTION_ITEM_ID_OFFSET;
function generateItemId(): number {
    actionItemIdGenerator++;
    return actionItemIdGenerator;
}

export class ActionItem extends common.ActionItem {
    private _androidPosition: dts.AndroidActionItemSettings = {
        position: enums.AndroidActionItemPosition.actionBar,
        systemIcon: undefined
    };
    private _itemId;
    constructor() {
        super();
        this._itemId = generateItemId();
    }

    public get android(): dts.AndroidActionItemSettings {
        return this._androidPosition;
    }
    public set android(value: dts.AndroidActionItemSettings) {
        throw new Error("ActionItem.android is read-only");
    }

    public _getItemId() {
        return this._itemId;
    }
}

export class AndroidActionBarSettings implements dts.AndroidActionBarSettings {
    private _actionBar: ActionBar;
    private _icon: string;
    private _iconVisibility: string = enums.AndroidActionBarIconVisibility.auto;

    public get icon(): string {
        return this._icon;
    }
    public set icon(value: string) {
        if (value !== this._icon) {
            this._icon = value;
            this._actionBar._onIconPropertyChanged();
        }
    }

    public get iconVisibility(): string {
        return this._iconVisibility;
    }
    public set iconVisibility(value: string) {
        if (value !== this._iconVisibility) {
            this._iconVisibility = value;
            this._actionBar._onIconPropertyChanged();
        }
    }

    constructor(actionBar: ActionBar) {
        this._actionBar = actionBar;
    }
}

export class NavigationButton extends ActionItem {

}

export class ActionBar extends common.ActionBar {
    private _appResources: android.content.res.Resources;
    private _android: AndroidActionBarSettings;
    private _toolbar: android.support.v7.widget.Toolbar;

    get android(): AndroidActionBarSettings {
        return this._android;
    }

    set android(value: AndroidActionBarSettings) {
        throw new Error("ActionBar.android is read-only");
    }

    get _nativeView() {
        return this._toolbar;
    }

    constructor() {
        super();

        this._appResources = application.android.context.getResources();
        this._android = new AndroidActionBarSettings(this);
    }

    public _createUI() {
        this._toolbar = new android.support.v7.widget.Toolbar(this._context);
        let ownerRef = new WeakRef(this);
        this._toolbar.setOnMenuItemClickListener(new android.support.v7.widget.Toolbar.OnMenuItemClickListener({
            onMenuItemClick: function (item: android.view.IMenuItem): boolean {
                let ownerValue = ownerRef.get();
                if (!ownerValue) {
                    return false;
                }
                let itemId = item.getItemId();
                return ownerValue._onAndroidItemSelected(itemId);
            }
        }));
    }

    public onLoaded() {
        super.onLoaded();
        this.update();
    }

    public update() {
        if (!this._toolbar) {
            return;
        }

        if (!this.page.frame || !this.page.frame._getNavBarVisible(this.page)) {
            this._toolbar.setVisibility(android.view.View.GONE);

            // If action bar is hidden - no need to fill it with items.
            return;
        }
        this._toolbar.setVisibility(android.view.View.VISIBLE);

        // Add menu items
        this._addActionItems();

        // Set title
        this._updateTitleAndTitleView();

        // Set home icon
        this._updateIcon();

        // Set navigation button
        this._updateNavigationButton();
    }

    public _onAndroidItemSelected(itemId: number): boolean {
        // Handle home button
        if (this.navigationButton && itemId === R_ID_HOME) {
            this.navigationButton._raiseTap();
            return true;
        }

        // Find item with the right ID;
        var menuItem: dts.ActionItem = undefined;
        var items = this.actionItems.getItems();
        for (let i = 0; i < items.length; i++) {
            if ((<ActionItem>items[i])._getItemId() === itemId) {
                menuItem = items[i];
                break;
            }
        }

        if (menuItem) {
            menuItem._raiseTap();
            return true;
        }

        return false;
    }

    public _updateNavigationButton() {
        let navButton = this.navigationButton;
        if (navButton && common.isVisible(navButton)) {
            if (navButton.android.systemIcon) {
                // Try to look in the system resources.
                let systemResourceId = getSystemResourceId(navButton.android.systemIcon);
                if (systemResourceId) {
                    this._toolbar.setNavigationIcon(systemResourceId);
                }
            }
            else if (navButton.icon) {
                let drawableOrId = getDrawableOrResourceId(navButton.icon, this._appResources);
                this._toolbar.setNavigationIcon(drawableOrId);
            }

            let navBtn = new WeakRef(navButton);
            this._toolbar.setNavigationOnClickListener(new android.view.View.OnClickListener({
                onClick: function (v) {
                    let owner = navBtn.get();
                    if (owner) {
                        owner._raiseTap();
                    }
                }
            }));
        }
        else {
            this._toolbar.setNavigationIcon(null);
        }
    }

    public _updateIcon() {
        var visibility = getIconVisibility(this.android.iconVisibility);
        if (visibility) {
            var icon = this.android.icon;
            if (types.isDefined(icon)) {
                var drawableOrId = getDrawableOrResourceId(icon, this._appResources);
                if (drawableOrId) {
                    this._toolbar.setLogo(drawableOrId);
                }
            }
            else {
                var defaultIcon = application.android.nativeApp.getApplicationInfo().icon;
                this._toolbar.setLogo(defaultIcon);
            }
        }
        else {
            this._toolbar.setLogo(null);
        }
    }

    public _updateTitleAndTitleView() {
        if (!this.titleView) {
            // No title view - show the title
            var title = this.title;
            if (types.isDefined(title)) {
                this._toolbar.setTitle(title);
            } else {
                var appContext = application.android.context;
                var appInfo = appContext.getApplicationInfo();
                var appLabel = appContext.getPackageManager().getApplicationLabel(appInfo);
                if (appLabel) {
                    this._toolbar.setTitle(appLabel);
                }
            }
        }
    }

    public _addActionItems() {
        var menu = this._toolbar.getMenu();
        var items = this.actionItems.getVisibleItems();

        menu.clear();
        for (var i = 0; i < items.length; i++) {
            var item = <ActionItem>items[i];
            var menuItem = menu.add(android.view.Menu.NONE, item._getItemId(), android.view.Menu.NONE, item.text + "");

            if (item.actionView && item.actionView.android) {
                // With custom action view, the menuitem cannot be displayed in a popup menu. 
                item.android.position = enums.AndroidActionItemPosition.actionBar;
                menuItem.setActionView(item.actionView.android);
                ActionBar._setOnClickListener(item);
            }
            else if (item.android.systemIcon) {
                // Try to look in the system resources.
                let systemResourceId = getSystemResourceId(item.android.systemIcon);
                if (systemResourceId) {
                    menuItem.setIcon(systemResourceId);
                }
            }
            else if (item.icon) {
                var drawableOrId = getDrawableOrResourceId(item.icon, this._appResources);
                if (drawableOrId) {
                    menuItem.setIcon(drawableOrId);
                }
                else {
                    throw new Error("Error loading icon from " + item.icon);
                }
            }

            var showAsAction = getShowAsAction(item);
            menuItem.setShowAsAction(showAsAction);
        }
    }

    private static _setOnClickListener(item: ActionItem): void {
        item.actionView.android.setOnClickListener(new android.view.View.OnClickListener({
            onClick: function (v: android.view.View) {
                item._raiseTap();
            }
        }));
    }

    public _onTitlePropertyChanged() {
        if (this._toolbar) {
            this._updateTitleAndTitleView();
        }
    }

    public _onIconPropertyChanged() {
        if (this._toolbar) {
            this._updateIcon();
        }
    }

    public _clearAndroidReference() {
        // don't clear _android field!
        this._toolbar = undefined;
    }

    public _addViewToNativeVisualTree(child: view.View, atIndex?: number): boolean {
        super._addViewToNativeVisualTree(child);

        if (this._toolbar && child._nativeView) {

            if (types.isNullOrUndefined(atIndex) || atIndex >= this._nativeView.getChildCount()) {
                this._toolbar.addView(child._nativeView);
            }
            else {
                this._toolbar.addView(child._nativeView, atIndex);
            }
            return true;
        }

        return false;
    }

    public _removeViewFromNativeVisualTree(child: view.View): void {
        super._removeViewFromNativeVisualTree(child);

        if (this._toolbar && child._nativeView) {
            this._toolbar.removeView(child._nativeView);

            ensureTrace();

            trace.notifyEvent(child, "childInLayoutRemovedFromNativeVisualTree");
        }
    }
}

function getDrawableOrResourceId(icon: string, resources: android.content.res.Resources): any {
    if (!types.isString(icon)) {
        return undefined;
    }

    ensureUtils();

    if (icon.indexOf(utils.RESOURCE_PREFIX) === 0) {
        var resourceId: number = resources.getIdentifier(icon.substr(utils.RESOURCE_PREFIX.length), 'drawable', application.android.packageName);
        if (resourceId > 0) {
            return resourceId;
        }
    }
    else {
        var drawable: android.graphics.drawable.BitmapDrawable;

        ensureImageSource();

        var is = imageSource.fromFileOrResource(icon);
        if (is) {
            drawable = new android.graphics.drawable.BitmapDrawable(is.android);
        }

        return drawable;
    }

    return undefined;
}

function getShowAsAction(menuItem: dts.ActionItem): number {
    switch (menuItem.android.position) {
        case enums.AndroidActionItemPosition.actionBarIfRoom:
            return android.view.MenuItem.SHOW_AS_ACTION_IF_ROOM;

        case enums.AndroidActionItemPosition.popup:
            return android.view.MenuItem.SHOW_AS_ACTION_NEVER;

        case enums.AndroidActionItemPosition.actionBar:
        default:
            return android.view.MenuItem.SHOW_AS_ACTION_ALWAYS;
    }
}

function getIconVisibility(iconVisibility: string): boolean {
    switch (iconVisibility) {
        case enums.AndroidActionBarIconVisibility.always:
            return true;

        case enums.AndroidActionBarIconVisibility.auto:
        case enums.AndroidActionBarIconVisibility.never:
        default:
            return false;
    }
}

function getSystemResourceId(systemIcon: string): number {
    return android.content.res.Resources.getSystem().getIdentifier(systemIcon, "drawable", "android");
}

export class ActionBarStyler implements style.Styler {
    // color
    private static setColorProperty(v: view.View, newValue: any) {
        var toolbar = (<android.support.v7.widget.Toolbar>v._nativeView);
        toolbar.setTitleTextColor(newValue);

    }

    private static resetColorProperty(v: view.View, nativeValue: any) {
        // there is no toolbar.getTitleTextColor - so default to black
        if (types.isNullOrUndefined(nativeValue)) {
            nativeValue = android.graphics.Color.BLACK;
        }
        (<android.support.v7.widget.Toolbar>v._nativeView).setTitleTextColor(nativeValue);
    }

    // background-color
    private static getBackgroundColorProperty(view: view.View): any {
        let toolbar = <android.support.v7.widget.Toolbar>view._nativeView;
        return toolbar.getBackground();
    }

    private static setBackgroundColorProperty(v: view.View, newValue: any) {
        var toolbar = (<android.support.v7.widget.Toolbar>v._nativeView);
        if (toolbar) {
            toolbar.setBackgroundColor(newValue);
        }
    }

    private static resetBackgroundColorProperty(v: view.View, nativeValue: any) {
        var toolbar = (<android.support.v7.widget.Toolbar>v._nativeView);
        if (toolbar) {
            toolbar.setBackgroundColor(nativeValue);
        }
    }

    public static registerHandlers() {
        style.registerHandler(style.colorProperty, new style.StylePropertyChangedHandler(
            ActionBarStyler.setColorProperty,
            ActionBarStyler.resetColorProperty), "ActionBar");
        style.registerHandler(style.backgroundColorProperty, new style.StylePropertyChangedHandler(
            ActionBarStyler.setBackgroundColorProperty,
            ActionBarStyler.resetBackgroundColorProperty, 
            ActionBarStyler.getBackgroundColorProperty), "ActionBar");
    }
}

ActionBarStyler.registerHandlers();
