// vim: et:ts=4:sw=4:sts=4:ft=js

/*@
Ox.ListMap <f:Ox.Element> ListMap Object
    () ->              <f> ListMap Object
    (options) ->       <f> ListMap Object
    (options, self) -> <f> ListMap Object
    options <o> Options object
        addPlace <f|null>
        height <n|256>
        labels <b|false>
        places <f|null>
        selected <a|[]>
        width <n|256>
    self    <o> shared private variable
@*/

Ox.ListMap = function(options, self) {

    var self = self || {},
        that = new Ox.Element({}, self)
            .defaults({
                addPlace: null,
                height: 256,
                labels: false,
                places: null,
                selected: [],
                width: 256
            })
            .addClass('OxListMap')
            .options(options || {})
            .css({
                width: self.options.width + 'px',
                height: self.options.height + 'px'
            });

    self.columns = [
        {
            addable: false, // fixme: implement
            id: 'id',
            unique: true,
            visible: false
        },
        {
            editable: true,
            id: 'name',
            operator: '+',
            removable: false,
            title: 'Name',
            visible: true,
            width: 144
        },
        {
            editable: true,
            id: 'geoname',
            removable: false,
            operator: '+',
            title: 'Geoname',
            visible: true,
            width: 192
        },
        {
            format: function(value) {
                return $('<img>')
                    .attr({
                        // fixme: not the right place to do this
                        src: Ox.PATH + 'Ox.Geo/png/icons/16/' + (value || 'NTHH') + '.png'
                    })
                    .css({
                        width: '14px',
                        height: '14px'
                    });
                    /*
                    .css({
                        width: '21px',
                        height: '14px'
                    })
                    .load(function() {
                        var $this = $(this);
                        Ox.print($this.width() / $this.height())
                        $this.css({
                            width: Math.round(14 * $this.width() / $this.height()) + 'px',
                            height: '14px',
                            padding: '1px 0 0 1px'
                        });
                    });
                    */
            },
            id: 'countryCode',
            operator: '+',
            title: 'Flag',
            visible: true,
            width: 48
        },
        {
            align: 'right',
            format: {type: 'area', args: [0]},
            id: 'size',
            operator: '-',
            title: 'Size',
            visible: true,
            width: 128
        },
        {
            align: 'right',
            format: toFixed,
            id: 'lat',
            operator: '+',
            title: 'Latitude',
            visible: true,
            width: 96
        },
        {
            align: 'right',
            format: toFixed,
            id: 'lng',
            operator: '+',
            title: 'Longitude',
            visible: true,
            width: 96
        },
        {
            align: 'right',
            format: toFixed,
            id: 'south',
            operator: '+',
            title: 'South',
            visible: false,
            width: 96
        },
        {
            align: 'right',
            id: 'west',
            operator: '+',
            title: 'West',
            visible: false,
            width: 96
        },
        {
            align: 'right',
            format: toFixed,
            id: 'north',
            operator: '+',
            title: 'North',
            visible: false,
            width: 96
        },
        {
            align: 'right',
            format: toFixed,
            id: 'east',
            operator: '+',
            title: 'East',
            visible: false,
            width: 96
        },
        {
            id: 'user',
            operator: '+',
            title: 'User',
            visible: false,
            width: 96
        },
        {
            format: 'date',
            id: 'created',
            operator: '-',
            title: 'Date Created',
            visible: false,
            width: 96,
        },
        {
            format: 'date',
            id: 'modified',
            operator: '-',
            title: 'Date Modified',
            visible: false,
            width: 96,
        },
        {
            align: 'right',
            id: 'matches',
            operator: '-',
            title: 'Matches',
            visible: false,
            width: 96,
        }
    ];

    self.$toolbar = new Ox.Bar({
        size: 24
    });

    self.$findElement = new Ox.FormElementGroup({
            elements: [
                self.$findSelect = new Ox.Select({
                        items: [
                            {id: 'all', title: 'Find: All'},
                            {id: 'name', title: 'Find: Name'},
                            {id: 'geoname', title: 'Find: Geoname'},
                            {id: 'country', title: 'Find: Country'}
                        ],
                        overlap: 'right',
                        width: 128
                    }),
                self.$findInput = new Ox.Input({
                        clear: true,
                        width: 192
                    })
            ]
        })
        .css({float: 'right', margin: '4px'})
        .appendTo(self.$toolbar)

    self.$list = new Ox.TextList({
            columns: self.columns,
            columnsRemovable: true,
            columnsVisible: true,
            items: self.options.places,
            pageLength: 100,
            scrollbarVisible: true,
            sort: [
                {key: 'name', operator: '+'}
            ]
        })
        .bindEvent({
            'delete': removeItem,
            init: initList,
            load: function() {
                that.triggerEvent('loadlist');
            },
            open: openItem,
            select: selectItem
        });

    self.$statusbar = new Ox.Bar({
            size: 24
        });

    self.$status = new Ox.Element()
        .css({paddingTop: '4px', margin: 'auto', textAlign: 'center'})
        .appendTo(self.$statusbar);

    self.mapResize = [
        Math.round(self.options.width * 0.25),
        Math.round(self.options.width * 0.5),
        Math.round(self.options.width * 0.75)
    ];

    if (Ox.isArray(self.options.places)) {
        init(self.options.places)
    } else {
        self.options.places({}, function(result) {
            Ox.print('$$$$', result.data.items)
            self.options.places({
                keys: self.columns.map(function(column) {
                    return column.id
                }),
                range: [0, result.data.items]
            }, function(result) {
                Ox.print('DATA', result)
                init(result.data.items);
            });
        });
    }

    function init(places) {
        //Ox.print('PLACES', places)
        self.$map = new Ox.Map({
                clickable: true,
                editable: true,
                findPlaceholder: 'Find on Map',
                height: self.options.height,
                places: places,
                statusbar: true,
                toolbar: true,
                width: self.mapResize[1],
                zoombar: true
            })
            .bindEvent({
                addplace: function(event, data) {
                    that.triggerEvent('addplace', data);
                },
                geocode: function(event, data) {
                    that.triggerEvent('geocode', data);
                },
                resize: function() {
                    self.$map.resizeMap(); // fixme: don't need event
                },
                selectplace: selectPlace
            });
        that.$element.replaceWith(
            that.$element = new Ox.SplitPanel({
                elements: [
                    {
                        element: new Ox.SplitPanel({
                            elements: [
                                {
                                    element: self.$toolbar,
                                    size: 24
                                },
                                {
                                    element: self.$list
                                },
                                {
                                    element: self.$statusbar,
                                    size: 24
                                }
                            ],
                            orientation: 'vertical'
                        })
                    },
                    {
                        element: self.$map,
                        resizable: true,
                        resize: self.mapResize,
                        size: self.mapResize[1]
                    }
                ],
                orientation: 'horizontal'
            }).$element
        );
    }

    function initList(event, data) {
        self.$status.html(data.items + ' place' + (data.items == 1 ? '' : 's'))
    }

    function openItem(event, data) {
        selectItem(event, data);
        self.$map.zoomToPlace(data.ids[0]);
    }

    function removeItem(event, data) {
        var id = data.ids[0];
        that.triggerEvent('removeplace', {id: id});
        self.$map.removePlace(id);
    }

    function selectItem(event, data) {
        Ox.print('selectItem', data.ids[0])
        var id = data.ids.length ? data.ids[0] : null;
        self.$map.options({selected: id});
        id && self.$map.panToPlace();
    }

    function selectPlace(event, data) {
        Ox.print('selectPlace', data, data.id)
        data.id && data.id[0] != '_' && self.$list.options({
            selected: data.id ? [data.id] : []
        });
    }

    function toFixed(val) {
        return val.toFixed(8);
    }

    /*@
    setOption <f> setOption
    @*/
    self.setOption = function(key, value) {
        Ox.print('ONCHANGE')
        if (key == 'height' || key == 'width') {
            Ox.print('ONCHANGE...')
            self.$map.options({
                height: self.options.height,
                width: self.options.width
            })
        } else if (key == 'selected') {
            self.$list.options({selected: value});
        }
    }

    /*@
    focusList <f> focusList
    @*/
    that.focusList = function() {
        self.$list.gainFocus();
        return that;
    }

    /*@
    reloadList <f> reloadList
    @*/
    that.reloadList = function() {
        self.$list.reloadList();
        return that;
    }

    /*@
    resizeMap <f> resizeMap
    @*/
    that.resizeMap = function() {
        Ox.print('Ox.ListMap.resizeMap()')
        self.$map.resizeMap();
        return that;
    };

    return that;

};