'use strict';

Ox.load(['Geo', 'UI'], function() {

    var items = Ox.COUNTRIES.map(function(country) {
            return Ox.extend({}, country, {
                flag: Ox.getFlagByCountryCode(country.code, 256),
                region: country.continent + ', ' + country.region
            });
        }),

        columns = [
            {
                id: 'code',
                operator: '+',
                title: 'Code',
                unique: true,
                visible: true,
                width: 64
            },
            {
                id: 'name',
                operator: '+',
                removable: false,
                title: 'Name',
                visible: true,
                width: 256
            },
            {
                id: 'continent',
                operator: '+',
                title: 'Continent',
                visible: true,
                width: 96
            },
            {
                format: function(value) {
                    return value.split(', ')[1];
                },
                id: 'region',
                operator: '+',
                title: 'Region',
                visible: true,
                width: 160
            },
            {
                align: 'right',
                format: function(value) {
                    return Ox.formatArea(value);
                },
                id: 'area',
                operator: '-',
                title: 'Area',
                visible: true,
                width: 112
            },
            {
                format: function(value) {
                    return Ox.formatDegrees(value, 'lat');
                },
                align: 'right',
                id: 'lat',
                operator: '-',
                title: 'Latitude',
                visible: true,
                width: 80
            },
            {
                format: function(value) {
                    return Ox.formatDegrees(value, 'lng');
                },
                align: 'right',
                id: 'lng',
                operator: '+',
                title: 'Longitude',
                visible: true,
                width: 80
            }
        ],

        itemSize = 288 + Ox.UI.SCROLLBAR_SIZE,

        ui = {
            find: '',
            include: {
                dependency: false,
                disputed: false,
                dissolved: false,
                exception: false
            },
            selected: [],
            sort: [{key: 'name', operator: '+'}],
            view: 'grid'
        },

        query = getQuery(),

        $toolbar = Ox.Bar({size: 24}).addClass('bar'),

        $view = Ox.ButtonGroup({
                buttons: [
                    {id: 'grid', title: 'grid', tooltip: 'View as Grid'},
                    {id: 'list', title: 'list', tooltip: 'View as List'}
                ],
                selectable: true,
                type: 'image',
                value: ui.view
            })
            .bindEvent({change: view})
            .appendTo($toolbar),

        $sort = Ox.Select({
                items: columns.filter(function(column) {
                    return column.id != 'flag';
                }).map(function(column) {
                    return {
                        id: column.id,
                        title: 'Sort by ' + column.title
                    };
                }),
                value: ui.sort[0].key,
                width: 128
            })
            .bindEvent({change: sort})
            [ui.view == 'grid' ? 'show' : 'hide']()
            .appendTo($toolbar),

        $order = Ox.Button(Ox.extend(getOptions(), {
                type: 'image'
            }))
            .bindEvent({click: order})
            [ui.view == 'grid' ? 'show' : 'hide']()
            .appendTo($toolbar),

        $find = Ox.Input({
                changeOnKeypress: true,
                clear: true,
                placeholder: 'Find',
                width: 192
            })
            .addClass('right')
            .bindEvent({change: find})
            .appendTo($toolbar),

        $include = Ox.MenuButton({
                items: [
                    {id: 'dependency', title: 'Include dependencies'},
                    {id: 'disputed', title: 'Include disputed countries'},
                    {id: 'dissolved', title: 'Include dissolved countries'},
                    {id: 'exception', title: 'Include other entities'}
                ].map(function(item) {
                    return Ox.extend(item, {checked: false});
                }),
                type: 'image'
            })
            .addClass('right')
            .bindEvent({change: include})
            .appendTo($toolbar),
        
        $list = renderList(),

        $statusbar = Ox.Bar({size: 16}),

        $status = Ox.Element().addClass('status').appendTo($statusbar),

        $listPanel = Ox.SplitPanel({
            elements: [
                {element: $toolbar, size: 24},
                {element: $list},
                {element: $statusbar, size: 16}
            ],
            orientation: 'vertical'
        }),

        $titlebar = Ox.Bar({size: 24}).addClass('bar'),

        $title = Ox.Label({
                width: itemSize - 28
            })
            .hide()
            .appendTo($titlebar),

        $deselect = Ox.Button({
                title: 'close',
                type: 'image'
            })
            .bindEvent({
                click: function() {
                    $list.options({selected: []});
                    select({ids: []});
                }
            })
            .hide()
            .appendTo($titlebar),

        $item = Ox.Element().addClass('item'),

        $itemPanel = Ox.SplitPanel({
                elements: [
                    {element: $titlebar, size: 24},
                    {element: $item},
                    {element: Ox.Bar({size: 16}), size: 16}
                ],
                orientation: 'vertical'
            }),

        $mainPanel = Ox.SplitPanel({
                elements: [
                    {element: $listPanel},
                    {element: $itemPanel, size: itemSize}
                ],
                orientation: 'horizontal'
            })
            .appendTo(Ox.$body);

    function find() {
        ui.find = $find.options('value');
        query = getQuery();
        $status.html('Loading...');
        $list.options({query: query});
    }

    function getOptions() {
        var operator = ui.sort[0].operator;
        return {
            title: operator == '+' ? 'up' : 'down',
            tooltip: operator == '+' ? 'Ascending' : 'Descending'
        };
    }

    function getQuery() {
        var query = {
            conditions: [{key: 'name', operator: '=', value: ui.find}],
            operator: '&'
        };
        Ox.forEach(ui.include, function(value, key) {
            !value && query.conditions.push(
                {key: key, operator: '=', value: void 0}       
            );
        });
        return query;
    }

    function include(data) {
        ui.include[data.id] = data.checked;
        find();
    }

    function init(data) {
        $status.html(
            (data.items || 'No') + ' countr'
            + (data.items == 1 ? 'y' : 'ies')
        );
    }

    function order() {
        ui.sort[0].operator = ui.sort[0].operator == '+' ? '-' : '+';
        $order.options(getOptions());
        $list.options({sort: Ox.clone(ui.sort, true)});
    }

    function renderItem() {
        var code = ui.selected[0];
        $item.empty();
        if (code) {
            $item.append(
                ui.view == 'grid'
                    ? Ox.TreeList({
                        data: Ox.getCountryByCode(code),
                        scrollbarVisible: true,
                        width: itemSize
                    })
                    : Ox.Element('<img>')
                        .addClass('flag')
                        .attr({src: Ox.getFlagByCountryCode(code, 256)})
            );
        }
    }

    function renderList() {
        return ui.view == 'grid'
            ? Ox.IconList({
                borderRadius: 16,
                fixedRatio: 1,
                item: function(data, sort, size) {
                    var key = sort[0].key == 'name' ? 'code' : sort[0].key,
                        column = Ox.getObjectById(columns, key),
                        info = (column.format || Ox.identity)(data[key]);
                    return {
                        height: size,
                        id: data.id,
                        info: info,
                        title: data.name,
                        url: data.flag,
                        width: size
                    };
                },
                items: items,
                keys: ['flag', 'name'],
                max: 1,
                pageLength: 1000,
                query: query,
                selected: ui.selected,
                size: 128,
                sort: Ox.clone(ui.sort, true),
                unique: 'code'
            })
            .bindEvent({
                init: init,
                select: select
            })
        : Ox.TextList({
                columns: columns,
                columnsMovable: true,
                columnsRemovable: true,
                columnsVisible: true,
                items: items,
                max: 1,
                pageLength: 1000,
                query: query,
                scrollbarVisible: true,
                selected: ui.selected,
                sort: Ox.clone(ui.sort, true)
            })
            .bindEvent({
                init: init,
                select: select,
                sort: sort
            });
    }

    function select(data) {
        var id = data.ids[0];
        if (id) {
            ui.selected = [id];
            data = $list.value(id);
            $title.options({title: data.name}).show();
            $deselect.show();
        } else {
            ui.selected = [];
            $title.hide();
            $deselect.hide();
        }
        renderItem();
    }

    function sort(data) {
        if (data.value) {
            data = {
                key: data.value,
                operator: Ox.getObjectById(columns, data.value).operator
            }
        }
        ui.sort = [{key: data.key, operator: data.operator}];
        $sort.options({value: data.key});
        $order.options(getOptions());
        $list.options({sort: Ox.clone(ui.sort, true)});
    }

    function view(data) {
        ui.view = data.value;
        $sort[ui.view == 'grid' ? 'show' : 'hide']();
        $order[ui.view == 'grid' ? 'show' : 'hide']();
        $list = renderList();
        $listPanel.replaceElement(1, $list);
        $list.gainFocus();
        renderItem();
    }

});