let tableData_global = []; // fetched date
let flags;

const doFetchCountries = () => {
    $.ajax({ url: "/items" }).done((data) => {
        if (data instanceof Array) tableData_global = data;
        else {
            tableData_global = [];
            tableData_global.push(data);
        }
    });
};

window.onload = () => {
    doFetchCountries();
    setup();
};

// mappa
const options = {
    lat: 0,
    lng: 0,
    zoom: 4,
    style: 'mapbox://styles/mapbox/traffic-night-v2',
    pitch: 50,
}

let WIDTH;
let HEIGHT;

const key = 'pk.eyJ1IjoicmljYXJkb2xhbmduZXIiLCJhIjoiY2pxano2enh2MG1qazN4bm5lajIzeDl3eiJ9.wK0MtuxLgJxDcGUksKMeKg';
let mappa;
let myMap;
let canvas;

// three
let scene;
let camera;
let renderer;
var light;

function setup_flags() {
    flags = [
        { id: "birth_rate_per_1000", name: "Birth Rate / 100", enabled: true, color: 0xff0000, scale: 0.1 },
        { id: "cell_phones_per_100", name: "Cell Phones / 100", enabled: false, color: 0xFFAA00, scale: 0.05 },
        { id: "children_per_woman", name: "Children / Woman", enabled: false, color: 0xAAFF00, scale: 1.0 },
        { id: "electricity_consumption_per_capita", name: "Electricity Consumption / Capita", enabled: false, color: 0x005AFF, scale: 0.00004 },
        { id: "gdp_per_capita", name: "GDP / Capita", enabled: false, color: 0xFFFF00, scale: 0.0001 },
        { id: "gdp_per_capita_growth", name: "GDP / Capita Growth", enabled: false, color: 0xE700FF, scale: 0.5 },
        { id: "inflation_annual", name: "Inflation Annual", enabled: false, color: 0x00F9FF, scale: 0.2 },
        { id: "internet_user_per_100", name: "Internet User / 100", enabled: false, color: 0xFF009A, scale: 0.05 },
        { id: "life_expectancy", name: "Life Expectancy", enabled: false, color: 0x00FF10, scale: 0.05 },
        { id: "military_expenditure_percent_of_gdp", name: "Military Expenditure % of GDP", enabled: false, color: 0x0027FF, scale: 1.0 },
    ];
}

function setup_checkboxes() {
    let checkboxes = "<table>";

    for (let i = 0; i < flags.length; i++) {
        let flag = flags[i];

        checkboxes += "<tr><td>";
        checkboxes += "<input type=\"checkbox\"";
        checkboxes += " id=\"" + flag.id + "\"";
        checkboxes += " onclick=\"checkbox_clicked('" + flag.id + "')\"";

        if (flag.enabled) {
            checkboxes += " checked";
        }

        checkboxes += ">" + flag.name + "</input>";

        checkboxes += "</td></tr>";
        checkboxes += "\n";
    }

    checkboxes += "</table>";

    let overlay = document.getElementById("overlay");

    if (overlay != null) {
        overlay.innerHTML = checkboxes;
    }
}

function checkbox_clicked(id) {
    let checkbox = document.getElementById(id);

    if (checkbox == null) {
        return;
    }

    for (let i = 0; i < flags.length; i++) {
        let flag = flags[i];

        if (flag.id == id) {
            flag.enabled = checkbox.checked;
            break;
        }
    }

    update();
}

function set_window_extents() {
    WIDTH = window.innerWidth;
    HEIGHT = window.innerHeight;

    canvas.width = WIDTH;
    canvas.height = HEIGHT;

    renderer.setSize(WIDTH, HEIGHT);

    camera = new THREE.PerspectiveCamera(75, WIDTH / HEIGHT, 0.1, 1000);
    camera.up = new THREE.Vector3(0, 0, 1);
}

function setup() {
    mappa = new Mappa('MapboxGL', key);
    myMap = mappa.tileMap(options);
    canvas = document.getElementById("mapa");

    scene = new THREE.Scene();
    renderer = new THREE.WebGLRenderer({ alpha: true, canvas: canvas });

    light = new THREE.PointLight(0xffffff, 1, 1000);
    light.position.set(-50, -50, 100);
    light.castShadow = true;
    light.shadow.mapSize.width = 512;
    light.shadow.mapSize.height = 512;
    light.shadow.camera.near = 0.5;
    light.shadow.camera.far = 1000;

    document.body.appendChild(renderer.domElement);

    myMap.overlay(canvas);
    myMap.onChange(update);

    set_window_extents();
    setup_flags();
    setup_checkboxes();

    update();
}

function setup_objects() {
    scene.remove.apply(scene, scene.children);
    scene.add(light);

    for (let i = 0; i < tableData_global.length; i++) {
        let long = tableData_global[i]["gps_long"];
        let lat = tableData_global[i]["gps_lat"];
        let enabled = 0;

        for (let j = 0; j < flags.length; j++) {
            let flag = flags[j];

            if (flag.enabled) {
                let value = tableData_global[i][flag.id];

                let height = value * flag.scale;
                let geometry = new THREE.BoxGeometry(1, 1, height);
                let material = new THREE.MeshBasicMaterial({ color: flag.color });
                let cube = new THREE.Mesh(geometry, material);
                cube.castShadow = true;
                cube.receiveShadow = true;

                const pos = myMap.latLngToPixel(lat, long);
                const vector = new THREE.Vector3();
                vector.set((pos.x / WIDTH) * 2 - 1, -(pos.y / HEIGHT) * 2 + 1, 0.5);
                vector.unproject(camera);
                const dir = vector.sub(camera.position).normalize();
                const distance = -camera.position.z / dir.z;
                const newPos = camera.position.clone().add(dir.multiplyScalar(distance));

                cube.position.set(newPos.x + enabled, newPos.y, newPos.z + height / 2);

                scene.add(cube);

                enabled++;
            }

        }
    }
}

function draw() { }

function update() {
    setup_objects();

    let pos = myMap.pixelToLatLng(WIDTH / 2, HEIGHT / 2);

    let zoom = myMap.zoom();
    let view;

    if (zoom == 0) {
        view = new THREE.Vector3(0, -10.0, 30.0);
    } else {
        view = new THREE.Vector3(0, -10 + (2.5 * (4 - zoom)), 30 + (7.5 * (4 - zoom)));
    }

    let center = new THREE.Vector3(pos.x, pos.y, 0);
    camera.position.set(view.x + center.x, view.y + center.y, view.z + center.z);
    camera.lookAt(center);

    renderer.render(scene, camera);
}

function on_resize() {
    set_window_extents();
    update();
}