/// <reference path="../../node_modules/@types/jquery/index.d.ts"/>

namespace RegionSelection {

    function foreach(data, callback: (value: any, key?: number | string, array?: Array<any>) => void) {
        for (let key in data) {
            if (data.hasOwnProperty(key) && typeof data[key] !== 'function') {
                callback(data[key], key, data);
            }
        }
    }

    class RegionsCollection {
        [index: number]: Region;

        public constructor(data: Region[]) {
            let length = 0;
            this.setLength = function (value: number) {
                length = value;
            };
            this.getLength = function () {
                return length;
            };
            foreach(data, (region: Region) => this.push(region));
        }

        get length() {
            return this.getLength();
        };

        set length(value: number) {
            this.setLength(value);
        }

        public setLength(value: number) {
        };

        public getLength(): number {
            return 0;
        };

        public push(item: Region) {
            Array.prototype.push.call(this, item);
        }

        public forEach(callback: (value: any, key?: number | string, array?: Array<any>) => void) {
            Array.prototype.forEach.call(this, callback);
        }

        public group(groupFunction: (region: Region) => string): { [groupName: string]: RegionsCollection } {
            let groups = {};
            this.forEach((region: Region) => {
                let groupName = groupFunction(region);
                if (groups[groupName] === undefined) {
                    groups[groupName] = new RegionsCollection([]);
                }
                groups[groupName].push(region);
            });
            return groups;
        }

        public sort(sortFunction: (region1: Region, region2: Region) => number): RegionsCollection {
            let data = [];
            this.forEach((region) => data.push(region));
            data.sort(sortFunction);
            return new RegionsCollection(data);
        }
    }

    class RegionSelectionBox {
        private selector: JQuery;
        private regions: RegionsCollection = new RegionsCollection([]);
        private box: JQuery;

        constructor(selector: JQuery) {
            this.selector = selector;
            if (this.selector.data('regions') !== undefined) {
                this.fillRegions(this.selector.data('regions'));
            }

            this.selector.on('click', this.showBox.bind(this));
        }

        private fillRegions(data) {
            foreach(eval(data), (value: RegionInterface) => {
                this.regions.push(new Region(value));
            });
        }

        private showBox(e: JQueryEventObject) {
            e.preventDefault();
            e.stopPropagation();

            if (this.box === undefined) {
                this.renderBox();
            }

            let box = this.box;

            let hide = function () {
                box.hide(0, () => {
                    $('body').off('click', hide);
                });
            }.bind(this);

            if (box.is(':visible')) {
                hide();
            } else {
                $('body').on('click', hide);
                box.show(0);
            }
        }

        private renderBox() {
            if (!$('.region__selection-box').length) {
                this.box = $('<div class="region__selection-box region-selection__box"></div>');
                let linkTemplate = '<a href="{link}" class="region-selection__link">{name}</a>';
                // let iconTemplate = '<img src="{icon}" class="region-selection__icon">';

                let grouped = this.regions.sort(function (region1: Region, region2: Region) {
                    return region1.caption < region2.caption ? -1 : region1.caption > region2.caption ? 1 : 0;
                }).group((region: Region) => {
                    return region.caption.charAt(0).toUpperCase();
                });

                foreach(grouped, (regionCollection: RegionsCollection, groupName) => {
                    let itemsList = $('<div class="region-selection__items-list"></div>');
                    itemsList.append($(`<div class="region-selection__list-letter">${groupName}</div>`));
                    foreach(regionCollection, (region: Region) => {
                        let item = $('<div class="region-selection__item"></div>').append(linkTemplate
                                .replace('{link}', region.link)
                                .replace('{name}', region.caption)
                            // .replace('{icon}', iconTemplate.replace('{icon}', region.icon))
                        );
                        itemsList.append($(item));
                    });
                    this.box.append(itemsList);
                });
                this.box.css('display', 'none');
                this.selector.parent().append(this.box);
            }
        }
    }

    interface RegionInterface {
        id: number;
        caption: string;
        link: string;
        icon: string;
    }

    class Region {

        constructor(data: RegionInterface) {
            this._id = data.id;
            this._caption = data.caption;
            this._link = data.link;
            this._icon = data.icon;
        }

        private _id: number;

        get id() {
            return this._id;
        }

        private _caption: string;

        get caption() {
            return this._caption;
        }

        private _link: string;

        get link(): string {
            return this._link;
        }

        private _icon: string;

        get icon(): string {
            return this._icon;
        }

    }

    export function createSelectionBox($object: JQuery) {
        return new RegionSelectionBox($object);
    }

}