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

namespace FancyCheckboxes {

    export class FancyCheckbox {
        public events: { [name: string]: { (responseText: string): void } [] } = {
            'error': [],
            'success': []
        };

        private $selector: JQuery;
        private checkboxData: any[];
        private selected: {} = {};

        public constructor($selector: JQuery) {
            this.$selector = $selector;
            this.checkboxData = [];
            this.populateCheckboxData(JSON.parse($selector.data('items') ? $selector.data('items').replace(/'/g, '"') : "[]"));
            this.$selector.click(this.onSelectorClick.bind(this));
            this.$selector.prev().append('<div class="selected-items"></div>');
            this.loadSelected();
        }

        private loadSelected() {
            let context = this;
            let first = true;
            let $selected = context.$selector.prev().find('.selected-items');
            this.selected = {};
            $selected.html('');
            console.dir($(this.$selector.data('field')).find(':selected'));
            $(this.$selector.data('field')).find(':selected').each(function () {
                context.selected[$(this).attr('value')] = $(this).html();
                if (!first) {
                    $selected.append(', ')
                }
                if (first) {
                    first = false;
                }
                $selected.append('<span>' + $(this).html() + '</span>');
            });
            console.dir(this.selected);
        }

        private onSelectorClick(event) {
            let context = this;
            let content = $('<div></div>');
            content.append('<div class="modal-header"><h3>' + this.$selector.html() + '</h3></div>');
            content.append('<div class="fancycheckboxes-items-container container">' + this.render().html() + '</div>');
            content.append('<div class="modal-footer"></div>');
            content.find('.modal-footer').append('<button type="submit" class="btn btn-primary">Выбрать</button>');
            let options = <FancyboxOptions> {
                content: '<div class="fancycheckboxes">' + content.html() + '</div>',
                type: 'html',
                modal: true,
                height: window.innerHeight,
                width: $('.mainBlock').outerWidth(),
                autoSize: false,
                afterClose: function () {
                    context.loadSelected();
                },
                afterShow: function () {
                    context.bindEvents();
                }
            };
            $.fancybox(options);
        }

        private bindEvents() {
            let context = this;
            let $fancy = $('.fancycheckboxes');
            $fancy.find('.more').each(function () {
                let $link = $(this);
                $link.on('click', function () {
                    $link.parent().animate({height: $link.parent()[0].scrollHeight}, 200, function () {
                        $link.parent().height('auto');
                        $link.remove();
                    });
                });
            });
            $fancy.find('.btn-primary').click(function () {
                $(context.$selector.data('field')).find('option').removeAttr('selected');
                $fancy.find('input:checked').each(function () {
                    console.dir($(context.$selector.data('field'))
                        .find('[value=' + $(this).attr('value') + ']'));
                    $(context.$selector.data('field'))
                        .find('[value=' + $(this).attr('value') + ']')
                        .prop('selected', 'selected');
                });

                $.fancybox.close();
            });
        }

        public checkChecked(id) {
            return this.selected.hasOwnProperty(id);
        }

        public on(eventName: string, callback: (responseText: string) => void) {
            this.events[eventName].push(callback);
            return this;
        }

        public trigger(eventName: string, ...args: any[]) {
            let context = this;
            for (let i in this.events[eventName]) {
                if (this.events[eventName].hasOwnProperty(i)) {
                    setTimeout(this.events[eventName][i].apply(context, args), 1);
                }
            }
        }

        private populateCheckboxData(checkboxData: ItemInterface[]) {
            checkboxData.sort(function (item1: ItemInterface, item2: ItemInterface) {
                return item1.value.localeCompare(item2.value);
            });
            for (let i in checkboxData) {
                if (checkboxData.hasOwnProperty(i)) {
                    if (checkboxData[i].items.length) {
                        let group = new CheckboxGroup(checkboxData[i], this);
                        this.checkboxData.push(group);
                    } else {
                        let item = new CheckboxItem(checkboxData[i], this);
                        this.checkboxData.push(item);
                    }
                }
            }
        }

        public render() {
            let items = $('<div></div>');
            this.checkboxData.forEach(function (item) {
                if (item instanceof CheckboxItem) {
                    let group = $('<div class="fancycheckboxes-group"></div>');
                    group.append(item.render());
                    items.append(group);
                } else {
                    items.append(item.render());
                }
            });
            items.find('.fancycheckboxes-group').each(function () {
                if ($(this).find('.fancycheckboxes-item').length > 5) {
                    $(this).append($('<a class="more">Все &raquo;</a>'));
                    $(this).height(150);
                }
            });
            return items;
        }
    }

    interface ItemInterface {
        id: number;
        value: string;
        items: ItemInterface[];
    }

    class CheckboxGroup {
        public items: any[];

        public name: string;
        private widget: FancyCheckbox;

        public constructor(item: ItemInterface, widget: FancyCheckbox) {
            this.widget = widget;
            this.name = item.value;
            this.items = [];
            this.populateCheckboxData(item.items);
        }

        private populateCheckboxData(checkboxData: ItemInterface[]) {
            checkboxData.sort(function (item1: ItemInterface, item2: ItemInterface) {
                return item1.value.localeCompare(item2.value);
            });
            for (let i in checkboxData) {
                if (checkboxData.hasOwnProperty(i)) {
                    if (checkboxData[i].items.length) {
                        let group = new CheckboxGroup(checkboxData[i], this.widget);
                        this.items.push(group);
                    } else {
                        let item = new CheckboxItem(checkboxData[i], this.widget);
                        this.items.push(item);
                    }
                }
            }
        }

        public render() {
            let group = $('<div class="fancycheckboxes-group"></div>');
            group.append($('<h4>' + this.name + '</h4>'));
            this.items.forEach(function (item) {
                group.append(item.render());
            });
            return group;
        }
    }

    class CheckboxItem {
        public id: number;
        public name: string;
        private widget: FancyCheckbox;

        public  constructor(item: ItemInterface, widget: FancyCheckbox) {
            this.id = item.id;
            this.name = item.value;
            this.widget = widget;
        }

        public render() {
            let item = $('<div class="fancycheckboxes-item"></div>');
            item.append($('<input type="checkbox" value="' + this.id + '" id="fchb_' + this.id + '" > <label for="fchb_' + this.id + '">' + this.name + '</label>'));
            if (this.widget.checkChecked(this.id)) {
                item.find('input').attr('checked', 'checked');
            }
            return item;
        }
    }


}