Ox.load({UI: {
    debug: true,
    hideScreen: true,
    showScreen: true,
    theme: 'modern'
}, Geo: {}}, function() {

    Ox.getJSON('json/cities50000.json', function(cities) {

        var places = cities.map(function(city, i) {
            var area = Math.max(city.population, 1) * 100,
                geoname = city.name + ', ' + Ox.getCountryByCode(city.country_code).name,
                latSize = Math.sqrt(area) / Ox.EARTH_CIRCUMFERENCE * 360,
                lngSize = Math.sqrt(area) * Ox.getDegreesPerMeter(city.latitude),
                marker = city.population > 10000000 ? {size: 24, color: [255, 0, 0]}
                    : city.population > 5000000 ? {size: 22, color: [255, 32, 0]}
                    : city.population > 2000000 ? {size: 20, color: [255, 64, 0]}
                    : city.population > 1000000 ? {size: 18, color: [255, 96, 0]}
                    : city.population > 500000 ? {size: 16, color: [255, 128, 0]}
                    : city.population > 200000 ? {size: 14, color: [255, 160, 0]}
                    : city.population > 100000 ? {size: 12, color: [255, 192, 0]}
                    : city.population > 50000 ? {size: 10, color: [255, 224, 0]}
                    : {size: 8, color: [255, 255, 0]};
            return {
                alternativeNames: [],
                area: area,
                countryCode: city.country_code,
                editable: true,
                geoname: geoname,
                geonameSort: getGeonameSort(geoname),
                id: Ox.encodeBase32(Ox.uid()),
                markerColor: marker.color,
                markerSize: marker.size,
                name: city.name,
                type: 'city',
                lat: city.latitude,
                lng: city.longitude,
                south: city.latitude - latSize / 2,
                west: city.longitude - lngSize / 2,
                north: city.latitude + latSize / 2,
                east: city.longitude + lngSize / 2
            };
        });

        var $listmap = new Ox.ListMap({
                addPlace: function(data, callback) {
                    var id = Ox.encodeBase32(Ox.uid());
                    Ox.print('addplace', getGeonameSort(data.geoname));
                    places.push(Ox.extend(data, {
                        geonameSort: getGeonameSort(data.geoname),
                        id: id
                    }));
                    callback({
                        data: {id: id},
                        result: {code: 200, text: 'OK'}
                    });
                },
                editPlace: function(data, callback) {
                    var place = Ox.getObjectById(places, data.id);
                    Ox.forEach(data, function(value, key) {
                        place[key] = value;
                        if (key == 'geoname') {
                            place.geonameSort = getGeonameSort(place.geoname);
                        }
                    });
                    callback({
                        result: {code: 200, text: 'OK'}
                    });
                },
                height: window.innerHeight,
                places: function(options, callback) {
                    // this simulates a remote API
                    Ox.print('OPTIONS', options)
                    var data = {};
                    // query, sort, range, area
                    if (Ox.isEmpty(options)) {
                        data = {
                            area: {
                                south: 90,
                                west: 180,
                                north: -90,
                                east: -180
                            },
                            items: places.length
                        };
                        places.forEach(function(place) {
                            ['south', 'west', 'north', 'east'].forEach(function(v) {
                                if (
                                    ((v == 'south' || v == 'west') && place[v] < data[v])
                                    || ((v == 'north' || v == 'east') && place[v] > data[v])
                                ) {
                                    data[v] = place[v];
                                }
                            });
                        });
                    } else {
                        data.items = places;
                        if (options.query) {
                            if (options.query.conditions[0].key == 'id') {
                                data.items = data.items.filter(function(place) {
                                    return place.id == options.query.conditions[0].value;
                                });
                            } else {
                                Ox.print('query', options)
                                data.items = data.items.filter(function(place) {
                                    var ret = true;
                                    options.query.conditions.forEach(function(condition) {
                                        if (condition.operator == '-') {
                                            if (
                                                place[condition.key] < condition.value[0]
                                                || place[condition.key] > condition.value[1]
                                            ) {
                                                ret = false;
                                            }
                                        } else { // '!-'
                                            if (
                                                place[condition.key] > condition.value[0]
                                                && place[condition.key] < condition.value[1]
                                            ) {
                                                ret = false;
                                            }
                                        }
                                        return ret;
                                    });
                                    return ret;
                                });
                            }
                        }
                        data.items.sort(function(a, b) {
                            if (options.sort[0].key == 'geoname') {
                                aValue = a.geonameSort;
                                bValue = b.geonameSort;
                            } else {
                                aValue = a[options.sort[0].key];
                                bValue = b[options.sort[0].key];
                            }
                            var ret = 0;
                            if (
                                (options.sort[0].operator == '+' && aValue < bValue)
                                || (options.sort[0].operator == '-' && aValue > bValue)
                            ) {
                                ret = -1;
                            } else if (
                                (options.sort[0].operator == '+' && aValue > bValue)
                                || (options.sort[0].operator == '-' && aValue < bValue)
                            ) {
                                ret = 1;
                            }
                            return ret;
                        });
                        if (options.ids) {
                            data.positions = {};
                            data.items.forEach(function(place, i) {
                                if (options.ids.indexOf(place.id) > -1) {
                                    data.positions[place.id] = i;
                                }
                            });
                            delete data.items;
                        } else if (options.range) {
                            data.items = data.items.filter(function(place, i) {
                                return i >= options.range[0] && i < options.range[1];
                            });
                        }
                    }
                    Ox.print('DATA', data)
                    callback({
                        data: data,
                        result: {code: 200, text: 'OK'}
                    });
                },
                removePlace: function(data, callback) {
                    var i = Ox.getPositionById(places, data.id);
                    places.splice(i, 1);
                    callback();
                },
                //showTypes: true,
                width: window.innerWidth
            })
            .bindEvent({
                geocode: function(event, data) {
                    //Ox.print(data);
                    Ox.print(JSON.stringify(data.results))
                }
            })
            .appendTo(Ox.UI.$body);

        $(window).resize(function() {
            Ox.print('RESIZE', window.innerHeight)
            $listmap.options({
                height: window.innerHeight,
                width: window.innerWidth
            });
        });

        window.$listmap = $listmap;

        function getGeonameSort(geoname) {
            var names = geoname.split(', ');
            if (!Ox.getCountryByGeoname(names[names.length - 1])) {
                names.push('~');
            }
            return names.reverse().join(', ');            
        }

    });

});