/*
 *  @Project:		Battle Brothers
 *	@Company:		Overhype Studios
 *
 *	@Copyright:		(c) Overhype Studios | 2013 - 2020
 * 
 *  @Author:		Overhype Studios
 *  @Date:			11.11.2017
 *  @Description:	Town Shop Dialog Module JS
 */
"use strict";

var WorldTownScreenShop =
{
	ItemOwner:
	{
		Stash: 'world-town-screen-shop-dialog-module.stash',
		Shop: 'world-town-screen-shop-dialog-module.shop'
	},

	ItemFlag:
	{
		Inserted: 0,
		Removed: 1,
		Updated: 2
    }
};

var WorldTownScreenShopDialogModule = function(_parent)
{
	this.mSQHandle = null;
	this.mParent = _parent;

    // event listener
    this.mEventListener = null;

	// generic containers
	this.mContainer = null;
    this.mDialogContainer = null;

    // list containers
    this.mStashListContainer = null;
    this.mStashListScrollContainer = null;
    this.mShopListContainer = null;
    this.mShopListScrollContainer = null;

    // assets labels
    this.mAssets = new WorldTownScreenAssets(_parent);

    // buttons
    this.mLeaveButton = null;

    // stash labels
    this.mStashSlotSizeContainer = null;
    this.mStashSlotSizeLabel = null;

    this.mStashSpaceUsed = 0;
    this.mStashSpaceMax = 0;

    // stash & found loot
    this.mStashSlots = null;
    this.mShopSlots = null;

	// lists
	this.mStashList = null;
	this.mShopList = null;

	// sort & filter
	this.mSortInventoryButton = null;
	this.mFilterAllButton = null;
	this.mFilterWeaponsButton = null;
	this.mFilterArmorButton = null;
	this.mFilterMiscButton = null;
    this.mFilterUsableButton = null;

	this.mIsRepairOffered = false;

    // generics
	this.mIsVisible = false;
};


WorldTownScreenShopDialogModule.prototype.isConnected = function ()
{
    return this.mSQHandle !== null;
};

WorldTownScreenShopDialogModule.prototype.onConnection = function (_handle)
{
	this.mSQHandle = _handle;

    // notify listener
    if (this.mEventListener !== null && ('onModuleOnConnectionCalled' in this.mEventListener))
	{
        this.mEventListener.onModuleOnConnectionCalled(this);
    }
};

WorldTownScreenShopDialogModule.prototype.onDisconnection = function ()
{
	this.mSQHandle = null;

    // notify listener
    if (this.mEventListener !== null && ('onModuleOnDisconnectionCalled' in this.mEventListener))
	{
        this.mEventListener.onModuleOnDisconnectionCalled(this);
    }
};

WorldTownScreenShopDialogModule.prototype.updateAssets = function (_data)
{
	this.mAssets.loadFromData(_data);
	this.updateItemPriceLabels(this.mShopSlots, this.mShopList, false);
}

WorldTownScreenShopDialogModule.prototype.createDIV = function (_parentDiv)
{
    var self = this;

    // create: containers (init hidden!)
    this.mContainer = $('<div class="l-shop-dialog-container display-none opacity-none"/>');
    _parentDiv.append(this.mContainer);
    this.mDialogContainer = this.mContainer.createDialog('', '', '', true, 'dialog-1024-768');

    // create tabs
    var tabButtonsContainer = $('<div class="l-tab-container"/>');
    this.mDialogContainer.findDialogTabContainer().append(tabButtonsContainer);
    
	//create assets
    this.mAssets.createDIV(tabButtonsContainer);

    // create content
    var content = this.mDialogContainer.findDialogContentContainer();

    // create stash
    var leftColumn = $('<div class="column is-left"/>');
    content.append(leftColumn);
    var headerRow = $('<div class="row is-header title-font-normal font-bold font-color-title">仓库</div>');
    leftColumn.append(headerRow);
	var contentRow = $('<div class="row is-content"/>');
    leftColumn.append(contentRow);
    var footerRow = $('<div class="row is-footer"/>');
    leftColumn.append(footerRow);

    var listContainerLayout = $('<div class="l-list-container is-left"></div>');
    contentRow.append(listContainerLayout);
    this.mStashListContainer = listContainerLayout.createList(1.24/*8.63*/);
    this.mStashListScrollContainer = this.mStashListContainer.findListScrollContainer();

    // create middle
    var middleColumn = $('<div class="column is-middle"/>');
    content.append(middleColumn);
    contentRow = $('<div class="row is-content"/>');
    middleColumn.append(contentRow);
	var buttonContainer = $('<div class="button-container"/>');
    contentRow.append(buttonContainer);

	// sort/filter
	var layout = $('<div class="l-button is-sort"/>');
    buttonContainer.append(layout);
    this.mSortInventoryButton = layout.createImageButton(Path.GFX + Asset.BUTTON_SORT, function()
	{
        self.notifyBackendSortButtonClicked();
    }, '', 3);

	var layout = $('<div class="l-button is-all-filter"/>');
    buttonContainer.append(layout);
    this.mFilterAllButton = layout.createImageButton(Path.GFX + Asset.BUTTON_ALL_FILTER, function()
	{
		self.mFilterAllButton.addClass('is-active');
		self.mFilterWeaponsButton.removeClass('is-active');
		self.mFilterArmorButton.removeClass('is-active');
        self.mFilterMiscButton.removeClass('is-active');
        self.mFilterUsableButton.removeClass('is-active');
		self.notifyBackendFilterAllButtonClicked();
    }, '', 3);
	self.mFilterAllButton.addClass('is-active');

	var layout = $('<div class="l-button is-weapons-filter"/>');
    buttonContainer.append(layout);
    this.mFilterWeaponsButton = layout.createImageButton(Path.GFX + Asset.BUTTON_WEAPONS_FILTER, function()
	{
		self.mFilterAllButton.removeClass('is-active');
		self.mFilterWeaponsButton.addClass('is-active');
		self.mFilterArmorButton.removeClass('is-active');
        self.mFilterMiscButton.removeClass('is-active');
        self.mFilterUsableButton.removeClass('is-active');
		self.notifyBackendFilterWeaponsButtonClicked();
    }, '', 3);

	var layout = $('<div class="l-button is-armor-filter"/>');
    buttonContainer.append(layout);
    this.mFilterArmorButton = layout.createImageButton(Path.GFX + Asset.BUTTON_ARMOR_FILTER, function()
	{
		self.mFilterAllButton.removeClass('is-active');
		self.mFilterWeaponsButton.removeClass('is-active');
		self.mFilterArmorButton.addClass('is-active');
        self.mFilterMiscButton.removeClass('is-active');
        self.mFilterUsableButton.removeClass('is-active');
		self.notifyBackendFilterArmorButtonClicked();
    }, '', 3);

	var layout = $('<div class="l-button is-misc-filter"/>');
    buttonContainer.append(layout);
    this.mFilterMiscButton = layout.createImageButton(Path.GFX + Asset.BUTTON_MISC_FILTER, function()
	{
		self.mFilterAllButton.removeClass('is-active');
		self.mFilterWeaponsButton.removeClass('is-active');
		self.mFilterArmorButton.removeClass('is-active');
        self.mFilterMiscButton.addClass('is-active');
        self.mFilterUsableButton.removeClass('is-active');
        self.notifyBackendFilterMiscButtonClicked();
    }, '', 3);

    var layout = $('<div class="l-button is-usable-filter"/>');
    buttonContainer.append(layout);
    this.mFilterUsableButton = layout.createImageButton(Path.GFX + Asset.BUTTON_USABLE_FILTER, function ()
    {
        self.mFilterAllButton.removeClass('is-active');
        self.mFilterWeaponsButton.removeClass('is-active');
        self.mFilterArmorButton.removeClass('is-active');
        self.mFilterMiscButton.removeClass('is-active');
        self.mFilterUsableButton.addClass('is-active');
        self.notifyBackendFilterUsableButtonClicked();
    }, '', 3);

    this.mStashSlotSizeContainer = $('<div class="slot-count-container"/>');
    buttonContainer.append(this.mStashSlotSizeContainer);
    var slotSizeImage = $('<img/>');
    slotSizeImage.attr('src', Path.GFX + Asset.ICON_BAG);
    this.mStashSlotSizeContainer.append(slotSizeImage);
    this.mStashSlotSizeLabel = $('<div class="label text-font-small font-bold font-color-value"/>');
    this.mStashSlotSizeContainer.append(this.mStashSlotSizeLabel);

    // create shop loot
    var rightColumn = $('<div class="column is-right"/>');
    content.append(rightColumn);
    headerRow = $('<div class="row is-header title-font-normal font-bold font-color-title">商店</div>');
    rightColumn.append(headerRow);
    contentRow = $('<div class="row is-content"/>');
    rightColumn.append(contentRow);

    listContainerLayout = $('<div class="l-list-container is-right"></div>');
    contentRow.append(listContainerLayout);
    this.mShopListContainer = listContainerLayout.createList(1.24/*8.63*/);
    this.mShopListScrollContainer = this.mShopListContainer.findListScrollContainer();


    // create footer button bar
    var footerButtonBar = $('<div class="l-button-bar"/>');
    this.mDialogContainer.findDialogFooterContainer().append(footerButtonBar);

    // create: buttons
    var layout = $('<div class="l-leave-button"/>');
    footerButtonBar.append(layout);
    this.mLeaveButton = layout.createTextButton("Leave", function()
	{
        self.notifyBackendLeaveButtonPressed();
    }, '', 1);

    this.mIsVisible = false;

    this.setupEventHandler();
};

WorldTownScreenShopDialogModule.prototype.destroyDIV = function ()
{
    this.mStashSlots = null;
    this.mShopSlots = null;

    this.mStashSlotSizeLabel.remove();
    this.mStashSlotSizeLabel = null;
    this.mStashSlotSizeContainer.empty();
    this.mStashSlotSizeContainer.remove();
    this.mStashSlotSizeContainer = null;

    this.mStashListContainer.destroyList();
    this.mStashListScrollContainer = null;
    this.mStashListContainer = null;

    this.mShopListContainer.destroyList();
    this.mShopListScrollContainer = null;
    this.mShopListContainer = null;

    this.mAssets.destroyDIV();
	//this.mAssets = null;

    this.mLeaveButton.remove();
    this.mLeaveButton = null;

    this.mDialogContainer.empty();
    this.mDialogContainer.remove();
    this.mDialogContainer = null;

    this.mContainer.empty();
    this.mContainer.remove();
    this.mContainer = null;
};

WorldTownScreenShopDialogModule.prototype.setupEventHandler = function ()
{
    var self = this;

    /*
    var dropStartHandler = function () {
        $(this).addClass("is-drop-target");
    };
    var dropEndHandler = function () {
        $(this).removeClass("is-drop-target");
    };
    */

    var dropHandler = function (ev, dd)
	{
        var drag = $(dd.drag);
        var drop = $(dd.drop);

        // do the swapping
        var sourceData = drag.data('item') || {};
        var targetData = drop.data('item') || {};

        var sourceOwner = (sourceData !== null && 'owner' in sourceData) ? sourceData.owner : null;
        var targetOwner = (targetData !== null && 'owner' in targetData) ? targetData.owner : null;

        if(sourceOwner === null || targetOwner === null)
        {
            console.error('Failed to drop item. Owner are invalid.');
            return;
        }

        // we don't allow swapping within the shop container
        if(sourceOwner === WorldTownScreenShop.ItemOwner.Shop && targetOwner === WorldTownScreenShop.ItemOwner.Shop)
        {
            //console.error('Failed to swap item within shop container. Not allowed.');
            return;
        }

        var sourceItemIdx = (sourceData !== null && 'index' in sourceData) ? sourceData.index : null;
        var targetItemIdx = (targetData !== null && 'index' in targetData) ? targetData.index : null;

        if(sourceItemIdx === null)
        {
            console.error('Failed to drop item. Source idx is invalid.');
            return;
        }

        self.swapItem(sourceItemIdx, sourceOwner, targetItemIdx, targetOwner);

        // workaround if the source container was removed before we got here
        if(drag.parent().length === 0)
        {
            $(dd.proxy).remove();
        }
        else
        {
            drag.removeClass('is-dragged');
        }
    };

    // create drop handler for the stash & shop container
    $.drop({ mode: 'middle' });

    this.mStashListContainer.data('item', { owner: WorldTownScreenShop.ItemOwner.Stash });
    //this.mStashListContainer.drop('start', dropStartHandler);
    this.mStashListContainer.drop(dropHandler);
    //this.mStashListContainer.drop('end', dropEndHandler);

    this.mShopListContainer.data('item', { owner: WorldTownScreenShop.ItemOwner.Shop });
    //this.mShopListContainer.drop('start', dropStartHandler);
    this.mShopListContainer.drop(dropHandler);
    //this.mShopListContainer.drop('end', dropEndHandler);
};

WorldTownScreenShopDialogModule.prototype.bindTooltips = function ()
{
	this.mAssets.bindTooltips();
    this.mStashSlotSizeContainer.bindTooltip({ contentType: 'ui-element', elementId: TooltipIdentifier.Stash.FreeSlots });
    this.mLeaveButton.bindTooltip({ contentType: 'ui-element', elementId: TooltipIdentifier.WorldTownScreen.ShopDialogModule.LeaveButton });

	this.mSortInventoryButton.bindTooltip({ contentType: 'ui-element', elementId: TooltipIdentifier.CharacterScreen.RightPanelHeaderModule.SortButton });
	this.mFilterAllButton.bindTooltip({ contentType: 'ui-element', elementId: TooltipIdentifier.CharacterScreen.RightPanelHeaderModule.FilterAllButton });
	this.mFilterWeaponsButton.bindTooltip({ contentType: 'ui-element', elementId: TooltipIdentifier.CharacterScreen.RightPanelHeaderModule.FilterWeaponsButton });
	this.mFilterArmorButton.bindTooltip({ contentType: 'ui-element', elementId: TooltipIdentifier.CharacterScreen.RightPanelHeaderModule.FilterArmorButton });
    this.mFilterMiscButton.bindTooltip({ contentType: 'ui-element', elementId: TooltipIdentifier.CharacterScreen.RightPanelHeaderModule.FilterMiscButton });
    this.mFilterUsableButton.bindTooltip({ contentType: 'ui-element', elementId: TooltipIdentifier.CharacterScreen.RightPanelHeaderModule.FilterUsableButton });
};

WorldTownScreenShopDialogModule.prototype.unbindTooltips = function ()
{
    this.mAssets.unbindTooltips();
	this.mStashSlotSizeContainer.unbindTooltip();
    this.mLeaveButton.unbindTooltip();

	this.mSortInventoryButton.unbindTooltip();
	this.mFilterAllButton.unbindTooltip();
	this.mFilterWeaponsButton.unbindTooltip();
	this.mFilterArmorButton.unbindTooltip();
    this.mFilterMiscButton.unbindTooltip();
    this.mFilterUsableButton.unbindTooltip();
};

WorldTownScreenShopDialogModule.prototype.create = function(_parentDiv)
{
    this.createDIV(_parentDiv);
    this.bindTooltips();
};

WorldTownScreenShopDialogModule.prototype.destroy = function()
{
    this.unbindTooltips();
    this.destroyDIV();
};

WorldTownScreenShopDialogModule.prototype.register = function (_parentDiv)
{
    console.log('WorldTownScreenShopDialogModule::REGISTER');

    if (this.mContainer !== null)
    {
        console.error('ERROR: Failed to register World Town Screen Shop Dialog Module. Reason: World Town Screen Shop Dialog Module is already initialized.');
        return;
    }

    if (_parentDiv !== null && typeof(_parentDiv) == 'object')
    {
        this.create(_parentDiv);
    }
};

WorldTownScreenShopDialogModule.prototype.unregister = function ()
{
    console.log('WorldTownScreenShopDialogModule::UNREGISTER');

    if (this.mContainer === null)
    {
        console.error('ERROR: Failed to unregister World Town Screen Shop Dialog Module. Reason: World Town Screen Shop Dialog Module is not initialized.');
        return;
    }

    this.destroy();
};

WorldTownScreenShopDialogModule.prototype.isRegistered = function ()
{
    if (this.mContainer !== null)
    {
        return this.mContainer.parent().length !== 0;
    }

    return false;
};


WorldTownScreenShopDialogModule.prototype.registerEventListener = function(_listener)
{
    this.mEventListener = _listener;
};


/*WorldTownScreenShopDialogModule.prototype.show = function (_withSlideAnimation)
{
	var self = this;

	var withAnimation = (_withSlideAnimation !== undefined && _withSlideAnimation !== null) ? _withSlideAnimation : true;
	if (withAnimation === true)
	{
		var offset = -this.mContainer.width();
		this.mContainer.css({ 'translateX': offset });
		this.mContainer.velocity("finish", true).velocity({ opacity: 1, translateX: 0 },
		{
			duration: Constants.SCREEN_SLIDE_IN_OUT_DELAY,
			easing: 'swing',
			begin: function ()
			{
				$(this).removeClass('display-none').addClass('display-block');
				self.notifyBackendModuleAnimating();
			},
			complete: function ()
			{
				self.mIsVisible = true;
				self.notifyBackendModuleShown();
			}
		});
	}
	else
	{
		this.mContainer.css({ opacity: 0 });
		this.mContainer.velocity("finish", true).velocity({ opacity: 1 },
		{
			duration: Constants.SCREEN_FADE_IN_OUT_DELAY,
			easing: 'swing',
			begin: function ()
			{
				$(this).removeClass('display-none').addClass('display-block');
				self.notifyBackendModuleAnimating();
			},
			complete: function ()
			{
				self.mIsVisible = true;
				self.notifyBackendModuleShown();
			}
		});
	}
};

WorldTownScreenShopDialogModule.prototype.hide = function ()
{
	var self = this;

	var offset = -this.mContainer.width();
	this.mContainer.velocity("finish", true).velocity({ opacity: 0, translateX: offset },
	{
		duration: Constants.SCREEN_SLIDE_IN_OUT_DELAY,
		easing: 'swing',
		begin: function ()
		{
			$(this).removeClass('is-center');
			self.notifyBackendModuleAnimating();
		},
		complete: function ()
		{
			self.mIsVisible = false;
			$(this).removeClass('display-block').addClass('display-none');
			self.notifyBackendModuleHidden();
		}
	});
};*/

WorldTownScreenShopDialogModule.prototype.show = function (_withSlideAnimation)
{
	var self = this;

    var withAnimation = (_withSlideAnimation !== undefined && _withSlideAnimation !== null) ? _withSlideAnimation : true;
    if (withAnimation === true)
    {
        var offset = -(this.mContainer.parent().width() + this.mContainer.width());
        this.mContainer.css({ 'left': offset });
        this.mContainer.velocity("finish", true).velocity({ opacity: 1, left: '0', right: '0' },
		{
            duration: Constants.SCREEN_SLIDE_IN_OUT_DELAY,
            easing: 'swing',
            begin: function ()
            {
                $(this).removeClass('display-none').addClass('display-block');
                self.notifyBackendModuleAnimating();
            },
            complete: function ()
            {
                self.mIsVisible = true;
                self.notifyBackendModuleShown();
            }
        });
    }
    else
    {
        this.mContainer.css({ opacity: 0 });
        this.mContainer.velocity("finish", true).velocity({ opacity: 1 },
		{
            duration: Constants.SCREEN_FADE_IN_OUT_DELAY,
            easing: 'swing',
            begin: function ()
            {
                $(this).removeClass('display-none').addClass('display-block');
                self.notifyBackendModuleAnimating();
            },
            complete: function ()
            {
                self.mIsVisible = true;
                self.notifyBackendModuleShown();
            }
        });
    }
};

WorldTownScreenShopDialogModule.prototype.hide = function ()
{
	var self = this;

    var offset = -(this.mContainer.parent().width() + this.mContainer.width());
    this.mContainer.velocity("finish", true).velocity({ opacity: 0, left: offset },
	{
        duration: Constants.SCREEN_SLIDE_IN_OUT_DELAY,
        easing: 'swing',
        begin: function ()
        {
            $(this).removeClass('is-center');
            self.notifyBackendModuleAnimating();
        },
        complete: function ()
        {
            self.mIsVisible = false;
            $(this).removeClass('display-block').addClass('display-none');
            self.notifyBackendModuleHidden();
        }
    });
};

WorldTownScreenShopDialogModule.prototype.isVisible = function ()
{
    return this.mIsVisible;
};

WorldTownScreenShopDialogModule.prototype.loadFromData = function (_data)
{
    if(_data === undefined || _data === null || !(typeof(_data) === 'object'))
	{
        return;
    }

    if('Title' in _data && _data.Title !== null)
	{
		 this.mDialogContainer.findDialogTitle().html(TranslateToolTip0_JianZhuNei(_data.Title));
	}

	if('SubTitle' in _data && _data.SubTitle !== null)
	{
		 this.mDialogContainer.findDialogSubTitle().html(TranslateWorldTownScreenShopDialogModule(_data.SubTitle));
	}

	if('HeaderImage' in _data && _data.HeaderImage !== null)
	{
		 this.mDialogContainer.findDialogHeaderImage().attr('src', Path.GFX + _data.HeaderImage);
	}

	if('IsRepairOffered' in _data && _data.IsRepairOffered !== null)
	{
		this.mIsRepairOffered = _data.IsRepairOffered;
	}

	if ('StashSpaceUsed' in _data)
	{
	    this.mStashSpaceUsed = _data.StashSpaceUsed;
	}

	if ('StashSpaceMax' in _data)
	{
	    this.mStashSpaceMax = _data.StashSpaceMax;
	}

	if('Stash' in _data && _data.Stash !== null)
	{
		this.loadStashData(_data.Stash);
	}

	if('Shop' in _data && _data.Shop !== null)
	{
		this.loadShopData(_data.Shop);
	}
};

WorldTownScreenShopDialogModule.prototype.loadStashData = function (_data)
{
    if(_data === undefined || _data === null || !jQuery.isArray(_data))
    {
        return;
    }

	this.mStashList = _data;

    if(this.mStashSlots === null)
    {
        this.mStashSlots = [];
    }

    // call by ref hack
    var arrayRef = { val: this.mStashSlots };
    var containerRef = { val: this.mStashListScrollContainer };

    this.assignItems(WorldTownScreenShop.ItemOwner.Stash, _data, arrayRef.val, containerRef.val);
};

WorldTownScreenShopDialogModule.prototype.loadShopData = function (_data)
{
    if(_data === undefined || _data === null || !jQuery.isArray(_data))
    {
        return;
    }

	this.mShopList = _data;

    if(this.mShopSlots === null)
    {
        this.mShopSlots = [];
    }

    // call by ref hack
    var arrayRef = { val: this.mShopSlots };
    var containerRef = { val: this.mShopListScrollContainer };

    this.assignItems(WorldTownScreenShop.ItemOwner.Shop, _data, arrayRef.val, containerRef.val);
};

WorldTownScreenShopDialogModule.prototype.assignItems = function (_owner, _items, _itemArray, _itemContainer)
{
	this.destroyItemSlots(_itemArray, _itemContainer);

    if(_items.length > 0)
    {
    	this.createItemSlots(_owner, _items.length, _itemArray, _itemContainer);

        for(var i = 0; i < _items.length; ++i)
        {
            // ignore empty slots
            if(_items[i] !== undefined && _items[i] !== null)
            {
                this.assignItemToSlot(_owner, _itemArray[i], _items[i]);
            }
        }

        this.updateItemPriceLabels(_itemArray, _items, _owner === WorldTownScreenShop.ItemOwner.Stash);

        if(_owner === WorldTownScreenShop.ItemOwner.Stash)
        {
            this.updateStashFreeSlotsLabel();
        }
    }
};

WorldTownScreenShopDialogModule.prototype.destroyItemSlots = function (_itemArray, _itemContainer)
{
    this.clearItemSlots(_itemArray);

    _itemContainer.empty();
    _itemArray.length = 0;
};

WorldTownScreenShopDialogModule.prototype.removeItemFromSlot = function(_slot)
{
    // remove item image
	_slot.assignListItemImage();
    _slot.assignListItemOverlayImage();
	_slot.assignListItemTooltip();
};

WorldTownScreenShopDialogModule.prototype.assignItemToSlot = function(_owner, _slot, _item)
{
    var remove = false;

    if(!('id' in _item) || !('imagePath' in _item))
    {
        remove = true;
    }

    if(remove === true)
    {
        this.removeItemFromSlot(_slot);
    }
    else
    {
        // update item data
        var itemData = _slot.data('item') || {};
        itemData.id = _item.id;
        _slot.data('item', itemData);

        // assign image
        _slot.assignListItemImage(Path.ITEMS + _item.imagePath);
        if(_item['imageOverlayPath']) _slot.assignListItemOverlayImage(Path.ITEMS + _item['imageOverlayPath']);
        else _slot.assignListItemOverlayImage();

        // show amount
        if(_item.showAmount === true && _item.amount != '')
        {
			_slot.assignListItemAmount('' + _item.amount, _item['amountColor']);
        }

        // show price
        if('price' in _item && _item.price !== null)
        {
            _slot.assignListItemPrice(_item.price);
        }

        // bind tooltip
        _slot.assignListItemTooltip(itemData.id, _owner);
    }
};

WorldTownScreenShopDialogModule.prototype.querySlotByIndex = function(_itemArray, _index)
{
    if(_itemArray === null || _itemArray.length === 0 || _index < 0 || _index >= _itemArray.length)
    {
        return null;
    }

    return _itemArray[_index];
};

WorldTownScreenShopDialogModule.prototype.createItemSlots = function (_owner, _size, _itemArray, _itemContainer)
{
    var screen = $('.world-town-screen');
    for(var i = 0; i < _size; ++i)
    {
        _itemArray.push(this.createItemSlot(_owner, _itemArray.length, _itemContainer, screen));
    }
};

WorldTownScreenShopDialogModule.prototype.clearItemSlots = function (_itemArray)
{
    if(_itemArray === null || _itemArray.length === 0)
    {
        return;
    }

    for(var i = 0; i < _itemArray.length; ++i)
    {
        // remove item image
        this.removeItemFromSlot(_itemArray[i]);
    }
};

WorldTownScreenShopDialogModule.prototype.createItemSlot = function (_owner, _index, _parentDiv, _screenDiv)
{
    var self = this;

    var result = _parentDiv.createListItem(true);
    result.attr('id', 'slot-index_' + _index);

    // update item data
    var itemData = result.data('item') || {};
    itemData.index = _index;
    itemData.owner = _owner;
    result.data('item', itemData);

    // add event handler
    var dropHandler = function (_source, _target)
	{
        var sourceData = _source.data('item');
        var targetData = _target.data('item');

        var sourceOwner = (sourceData !== null && 'owner' in sourceData) ? sourceData.owner : null;
        var targetOwner = (targetData !== null && 'owner' in targetData) ? targetData.owner : null;

        if(sourceOwner === null || targetOwner === null)
        {
            console.error('Failed to drop item. Owner are invalid.');
            return;
        }

        var sourceItemIdx = (sourceData !== null && 'index' in sourceData) ? sourceData.index : null;
        var targetItemIdx = (targetData !== null && 'index' in targetData) ? targetData.index : null;

        if(sourceItemIdx === null)
        {
            console.error('Failed to drop item. Source idx is invalid.');
            return;
        }

        self.swapItem(sourceItemIdx, sourceOwner, targetItemIdx, targetOwner);
    };

    var dragEndHandler = function (_source, _target)
	{
        if(_source.length === 0 || _target.length === 0)
        {
            return false;
        }

        var sourceData = _source.data('item');
        var targetData = _target.data('item');

        var sourceOwner = (sourceData !== null && 'owner' in sourceData) ? sourceData.owner : null;
        var targetOwner = (targetData !== null && 'owner' in targetData) ? targetData.owner : null;
        var itemIdx = (sourceData !== null && 'index' in sourceData) ? sourceData.index : null;

        if(sourceOwner === null || targetOwner === null)
        {
            console.error('Failed to drop item. Owner is invalid.');
            return false;
        }

        // we don't allow swapping within the shop container
        if(sourceOwner === WorldTownScreenShop.ItemOwner.Shop && targetOwner === WorldTownScreenShop.ItemOwner.Shop)
        {
            //console.error('Failed to swap item within shop container. Not allowed.');
            return false;
        }

        // we don't allow swapping if there is not enough money or space left
        if(sourceOwner === WorldTownScreenShop.ItemOwner.Shop)
        {
            return self.hasEnoughMoneyToBuy(itemIdx) && self.isStashSpaceLeft();
        }

        return true;
    };

    result.assignListItemDragAndDrop(_screenDiv, null, dragEndHandler, _owner === WorldTownScreenShop.ItemOwner.Stash ? dropHandler : null);

    result.assignListItemRightClick(function (_item, _event)
	{
        var data = _item.data('item');

        var isEmpty = (data !== null && 'isEmpty' in data) ? data.isEmpty : true;
        var owner = (data !== null && 'owner' in data) ? data.owner : null;
        //var itemId = (data !== null && 'id' in data) ? data.id : null;
        var itemIdx = (data !== null && 'index' in data) ? data.index : null;
        var destroyItem = false;
		var repairItem = KeyModiferConstants.AltKey in _event && _event[KeyModiferConstants.AltKey] === true;

        if(/*doSomething &&*/ isEmpty === false && owner !== null /*&& itemId !== null*/ && itemIdx !== null)
        {
            // buy, sell or destroy
            switch(owner)
            {
                case WorldTownScreenShop.ItemOwner.Stash:
                {
                    if (repairItem === true)
                    {
                        //console.info('destroy');
                        self.repairItem(itemIdx);
                    }
                    else
                    {
                        //console.info('sell');
                        self.swapItem(itemIdx, owner, null, WorldTownScreenShop.ItemOwner.Shop);
                    }
                } break;
                case WorldTownScreenShop.ItemOwner.Shop:
                {
                    if (destroyItem !== true)
                    {
                        //console.info('buy');
                        /*if(*/self.swapItem(itemIdx, owner, null, WorldTownScreenShop.ItemOwner.Stash);//))
// 						{
// 							var slot = self.querySlotByIndex(self.mShopSlots, data.index);
// 							slot.assignListItemImage();
// 						}
                    }
                } break;
            }
        }
    });

    return result;
};

WorldTownScreenShopDialogModule.prototype.repairItem = function(_itemIdx)
{
    var self = this;
    this.notifyBackendRepairItem(_itemIdx, function(_result)
    {
        if(_result.Item != null)
        {
            self.updateSlotItem(WorldTownScreenShop.ItemOwner.Stash, self.mStashSlots, _result.Item, _itemIdx, WorldTownScreenShop.ItemFlag.Updated);
        }

        self.mParent.loadAssetData(_result.Assets);
    });
}

WorldTownScreenShopDialogModule.prototype.swapItem = function (_sourceItemIdx, _sourceItemOwner, _targetItemIdx, _targetItemOwner)
{
    var self = this;
    this.notifyBackendSwapItem(_sourceItemIdx, _sourceItemOwner, _targetItemIdx, _targetItemOwner, function (data)
    {
        if (data === undefined || data == null || typeof (data) !== 'object')
        {
            console.error("ERROR: Failed to swap item. Reason: Invalid data result.");
            return;
        }

        // error?
        if (data.Result != 0)
        {
            if (data.Result == ErrorCode.NotEnoughMoney)
            {
                self.mAssets.mMoneyAsset.shakeLeftRight();
            }
            else if (data.Result == ErrorCode.NotEnoughStashSpace)
            {
                self.mStashSlotSizeContainer.shakeLeftRight();
            }
            else
            {
                console.error("Failed to swap item. Reason: Unknown");
            }

            return;
        }

        // update assets
        self.mParent.loadAssetData(data.Assets);

        if ('StashSpaceUsed' in data)
        {
            self.mStashSpaceUsed = data.StashSpaceUsed;
        }

        if ('StashSpaceMax' in data)
        {
            self.mStashSpaceMax = data.StashSpaceMax;
        }

        if ('Stash' in data)
        {
            self.updateStashList(data.Stash);
        }

        if ('Shop' in data)
        {
            self.updateShopList(data.Shop);
        }
    });
};

WorldTownScreenShopDialogModule.prototype.updateStashList = function (_data)
{
    if(this.mStashList === null || !jQuery.isArray(this.mStashList) || this.mStashList.length === 0)
    {
        this.loadStashData(_data);
        return;
    }

    // stash size changed (shouldn't happen)
    if(this.mStashList.length !== _data.length)
    {
        console.error('ERROR: Failed to update stash. Stash changed in size.');
        return;
    }

    // check stash for changes
    for(var i = 0; i < this.mStashList.length; ++i)
    {
        var sourceItem = this.mStashList[i];
        var targetItem = _data[i];

        // item added to stash slot
        if(sourceItem === null && targetItem !== null)
        {
            if('id' in targetItem)
            {
                //console.info('STASH: Item inserted (Index: ' + i + ')');
                this.mStashList[i] = targetItem;
				this.updateSlotItem(WorldTownScreenShop.ItemOwner.Stash, this.mStashSlots, targetItem, i, WorldTownScreenShop.ItemFlag.Inserted);
            }
        }

        // item removed from stash slot
        else if(sourceItem !== null && targetItem === null)
        {
            //console.info('STASH: Item removed (Index: ' + i + ')');
            this.mStashList[i] = targetItem;
			this.updateSlotItem(WorldTownScreenShop.ItemOwner.Stash, this.mStashSlots, targetItem, i, WorldTownScreenShop.ItemFlag.Removed);
        }

        // item might have changed within stash slot
        else
        {
            if((sourceItem !== null && targetItem !== null) && ('id' in sourceItem && 'id' in targetItem) && (sourceItem.id !== targetItem.id))
            {
                //console.info('STASH: Item updated (Index: ' + i + ')');
                this.mStashList[i] = targetItem;
				this.updateSlotItem(WorldTownScreenShop.ItemOwner.Stash, this.mStashSlots, targetItem, i, WorldTownScreenShop.ItemFlag.Updated);
            }
        }
    }
};

WorldTownScreenShopDialogModule.prototype.updateShopList = function (_data)
{
    if(this.mShopList === null || !jQuery.isArray(this.mShopList) || this.mShopList.length === 0)
    {
		this.loadShopData(_data);
        return;
    }

    // shop list changed in length, this means we removed or added something to / from stash
//     if(this.mShopList.length !== _data.length)
//     {
//         this.loadShopData(_data);
//         return;
//     }

	// create more slots?
	if(_data.length > this.mShopSlots.length)
	{
		this.createItemSlots(WorldTownScreenShop.ItemOwner.Shop, _data.length - this.mShopSlots.length, this.mShopSlots, this.mShopListScrollContainer);
	}

    // check shop for changes
	var maxLength = this.mShopList.length >= _data.length ? this.mShopList.length : _data.length;

    for(var i = 0; i < maxLength; ++i)
    {
        var oldItem = this.mShopList[i];
        var newItem = _data[i];

        // item added to shop slot
        if(i >= this.mShopList.length || (oldItem === null && newItem !== null))
        {
			//console.info('SHOP: Item inserted (Index: ' + i + ')');
			this.updateSlotItem(WorldTownScreenShop.ItemOwner.Shop, this.mShopSlots, newItem, i, WorldTownScreenShop.ItemFlag.Inserted);
        }

        // item removed from shop slot
        else if(i >= _data.length || (oldItem !== null && newItem === null))
        {
			//console.info('SHOP: Item removed (Index: ' + i + ')');
			this.updateSlotItem(WorldTownScreenShop.ItemOwner.Shop, this.mShopSlots, oldItem, i, WorldTownScreenShop.ItemFlag.Removed);
        }

        // item might have changed within shop slot
        else
        {
            if((oldItem !== null && newItem !== null) && ('id' in oldItem && 'id' in newItem))
            {
				if(oldItem.id !== newItem.id)
				{
					//console.info('SHOP: Item updated (Index: ' + i + ')');
					this.updateSlotItem(WorldTownScreenShop.ItemOwner.Shop, this.mShopSlots, newItem, i, WorldTownScreenShop.ItemFlag.Updated);
				}
				else
				{
					 this.updateItemPriceLabel(this.mShopSlots[i], newItem, false);
				}
            }			
        }
    }

	// update list
	this.mShopList = _data;
};

WorldTownScreenShopDialogModule.prototype.updateItemPriceLabel = function (_slot, _item, _positiveColor)
{
    var positiveColor = _positiveColor || false;
    var currentMoney = this.mAssets.getValues().Money;

    if(_item !== null)
    {
        if('price' in _item && _item.price !== null)
        {
            _slot.assignListItemPriceColor(positiveColor || currentMoney >= _item.price);
        }
    }
};

WorldTownScreenShopDialogModule.prototype.updateItemPriceLabels = function (_itemArray, _items, _allPositiveColors)
{
    if(_items == null || _itemArray == null)
	{
		return;
	}

	var allPositiveColors = _allPositiveColors || false;
    var currentMoney = this.mAssets.getValues().Money;

    for(var i = 0; i < _items.length; ++i)
    {
        // ignore empty slots
        if(_items[i] !== null)
        {
            var item = _items[i];

            if('price' in item && item.price !== null)
            {
				_itemArray[i].assignListItemPriceColor(allPositiveColors || currentMoney >= item.price);
            }
        }
    }
};

WorldTownScreenShopDialogModule.prototype.updateSlotItem = function (_owner, _itemArray, _item, _index, _flag)
{
    var slot = this.querySlotByIndex(_itemArray, _index);
    if(slot === null)
    {
        console.error('ERROR: Failed to update slot item: Reason: Invalid slot index: ' + _index);
        return;
    }

    switch(_flag)
    {
        case WorldTownScreenShop.ItemFlag.Inserted:
        case WorldTownScreenShop.ItemFlag.Updated:
        {
            this.removeItemFromSlot(slot);
            this.assignItemToSlot(_owner, slot, _item);
            this.updateItemPriceLabel(slot, _item, _owner === WorldTownScreenShop.ItemOwner.Stash);
			break;
        }
        case WorldTownScreenShop.ItemFlag.Removed:
        {
            this.removeItemFromSlot(slot);
			break;
        } 
    }

    if(_owner === WorldTownScreenShop.ItemOwner.Stash)
    {
        this.updateStashFreeSlotsLabel();
    }
};

WorldTownScreenShopDialogModule.prototype.updateStashFreeSlotsLabel = function ()
{
    var statistics = this.getStashStatistics();
    this.mStashSlotSizeLabel.html('' + statistics.used + '/' + statistics.size);

    if(statistics.used >= statistics.size)
    {
        this.mStashSlotSizeLabel.removeClass('font-color-value').addClass('font-color-negative-value');
    }
    else
    {
        this.mStashSlotSizeLabel.removeClass('font-color-negative-value').addClass('font-color-value');
    }
};

WorldTownScreenShopDialogModule.prototype.hasEnoughMoneyToBuy = function (_itemIdx)
{
    if(_itemIdx >= 0 && _itemIdx < this.mShopList.length)
    {
        var item = this.mShopList[_itemIdx];

        if(item !== null && 'price' in item && item.price !== null)
        {
            return this.mAssets.getValues().Money >= item.price;
        }
    }

    return false;
};

WorldTownScreenShopDialogModule.prototype.isStashSpaceLeft = function ()
{
    for(var i = 0; i < this.mStashList.length; ++i)
    {
        if(this.mStashList[i] === null)
            return true;
    }

    return false;
};

WorldTownScreenShopDialogModule.prototype.getStashStatistics = function ()
{
    /*var usedSpace = 0;

    for(var i = 0; i < this.mStashList.length; ++i)
    {
        if (this.mStashList[i] !== null)
            ++usedSpace;
    }*/

    return { size: this.mStashSpaceMax, used: this.mStashSpaceUsed };
};

WorldTownScreenShopDialogModule.prototype.notifyBackendModuleShown = function ()
{
    SQ.call(this.mSQHandle, 'onModuleShown');
};

WorldTownScreenShopDialogModule.prototype.notifyBackendModuleHidden = function ()
{
    SQ.call(this.mSQHandle, 'onModuleHidden');
};

WorldTownScreenShopDialogModule.prototype.notifyBackendModuleAnimating = function ()
{
    SQ.call(this.mSQHandle, 'onModuleAnimating');
};

WorldTownScreenShopDialogModule.prototype.notifyBackendLeaveButtonPressed = function ()
{
    SQ.call(this.mSQHandle, 'onLeaveButtonPressed');
};

WorldTownScreenShopDialogModule.prototype.notifyBackendRepairItem = function (_itemIdx, _callback)
{
    SQ.call(this.mSQHandle, 'onRepairItem', _itemIdx, _callback);
};


WorldTownScreenShopDialogModule.prototype.notifyBackendSwapItem = function (_sourceItemIdx, _sourceItemOwner, _targetItemIdx, _targetItemOwner, _callback)
{
    SQ.call(this.mSQHandle, 'onSwapItem', [_sourceItemIdx, _sourceItemOwner, _targetItemIdx, _targetItemOwner], _callback);
};


WorldTownScreenShopDialogModule.prototype.notifyBackendSortButtonClicked = function () 
{
    SQ.call(this.mSQHandle, 'onSortButtonClicked');
}

WorldTownScreenShopDialogModule.prototype.notifyBackendFilterAllButtonClicked = function ()
{
	SQ.call(this.mSQHandle, 'onFilterAll');
};

WorldTownScreenShopDialogModule.prototype.notifyBackendFilterWeaponsButtonClicked = function ()
{
	SQ.call(this.mSQHandle, 'onFilterWeapons');
};

WorldTownScreenShopDialogModule.prototype.notifyBackendFilterArmorButtonClicked = function ()
{
	SQ.call(this.mSQHandle, 'onFilterArmor');
};

WorldTownScreenShopDialogModule.prototype.notifyBackendFilterMiscButtonClicked = function ()
{
	SQ.call(this.mSQHandle, 'onFilterMisc');
};

WorldTownScreenShopDialogModule.prototype.notifyBackendFilterUsableButtonClicked = function ()
{
    SQ.call(this.mSQHandle, 'onFilterUsable');
};