
var ANIMATION_SPEED = 1000;
var ANIMATION_SPEED_SHOW = new Big(1);

const INITIAL_PAUSE = 0;
let time_ani = 0;

var new_mapstyle = "https://gsi-cyberjapan.github.io/gsivectortile-mapbox-gl-js/pale.json"
var initial_data

const dataFilter = new deck.DataFilterExtension({
filterSize: 1,
// Enable for higher precision, e.g. 1 second granularity
// See DataFilterExtension documentation for how to pick precision
fp64: false
});

//const colors = {0: [253, 128, 93], 'others': [23, 184, 190]};
let req ;
let get_data;
var colors = {};
i = 0;
while (i < 10000) {
    colors[i] = [rand(0, 255),rand(0, 255),rand(0, 255)];
    i++;
}
colors[0] = [23, 184, 190]
colors['others'] = [23, 184, 190]

// random number generator
function rand(frm, to) {
   return ~~(Math.random() * (to - frm)) + frm;
}

const getColor = i => {
    if (typeof i === 'undefined' || !(i in colors)) {i = 'others'};
    return colors[i];
}

const getVisible = i => {
    var flag  = false;
    if (i === 0) {if (document.getElementById("trip").checked) {flag = true}}
    if (i === 1) {if (document.getElementById("point").checked) {flag = true}}
    if (i === 2) {if (document.getElementById("heat").checked) {flag = true}}
    return flag ;
}

function bbox(json) {
    let points = [];
    for (let e of json){
        points = points.concat(e.path);
    }
    const b = turf.bbox(turf.multiPoint(points))
    return [[Number(b[0]), Number(b[3])], [Number(b[2]), Number(b[1])]];
}

function interval_timestamps(json) {
    let timestamps = [];
    for (let e of json){
        timestamps = timestamps.concat(e.timestamps);
    }
    return [Math.min(...timestamps), Math.max(...timestamps)]; 
}



var style_sample = 
[
    'interpolate',
    ['linear'],
    ['get', 'cnt']
]
const aryMax = function (a, b) {return Math.max(a, b);}
const aryMin = function (a, b) {return Math.min(a, b);}

var df_data = []
var value_list = []

var grad_style = ['#fdf7f7','#fceded','#f8dcdc','#f1b8b8','#ea9595']
//Select2
$(document).ready(function() {
    $("#overlay").fadeIn(300)
    // var map = new maplibregl.Map({
    //     container: 'map', // container id
    //     style: 'style/dark.json', // style URL
    //     center: [0, 0], // starting position [lng, lat]
    //     zoom: 1 // starting zoom
    // });
    deck.carto.setDefaultCredentials({
        username: 'public',
        apiKey: 'default_public',
    });
    const view = new deck.WebMercatorViewport({width: document.body.clientWidth, height: document.body.clientHeight});

    let request = {
        table: "df-i",
    };
    $.ajax({
        type: "POST",
        url: '/cgi-bin/mod_005_load.py',
        data: JSON.stringify(request),
        dataType: "json",
        success: function(data) {
            if (Object.keys(data).length  === 0) {
                custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。');
                return;
            }
            initial_data = data
            let options = $.map(data.year_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#year').append(options);

            options = $.map(data.month_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#month').append(options);

            options = $.map(data.date_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#date').append(options);

            options = $.map(data.hour_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#time').append(options);

            options = $.map(data.holiday_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#holyday').append(options);

            options = $.map(data.week_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#yobi').append(options);
            options = $.map(data.attr1_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#attr1').append(options);


            options = $.map(data.attr2_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#attr2').append(options);

            options = $.map(data.attr3_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#attr3').append(options);

            options = $.map(data.attr4_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#attr4').append(options);

            options = $.map(data.attr5_list, function(text, value) {
                let option = $('<option>', {value: text, text: text});
                return option;
            });
            $('#attr5').append(options);
            $('.multiple').multiselect({
                maxHeight: 200,
                includeSelectAllOption: true,
                includeResetOption: true,
            });

            $("#year").val($("#year").val().concat(data.init_year)); 
            $('#year').multiselect("refresh");
            $("#month").val($("#month").val().concat(data.init_month)); 
            $('#month').multiselect("refresh");

            $("#date").multiselect('selectAll', false);
            $("#time").multiselect('selectAll', false);
            $("#holyday").multiselect('selectAll', false);
            $("#yobi").multiselect('selectAll', false);
            $("#attr1").multiselect('selectAll', false);
            $("#attr2").multiselect('selectAll', false);
            $("#attr3").multiselect('selectAll', false);
            $("#attr4").multiselect('selectAll', false);
            $("#attr5").multiselect('selectAll', false);
            if (data.attr1_list[0] == 'すべて') {$('#attr1_div').css({"visibility":"hidden", });}
            if (data.attr2_list[0] == 'すべて') {$('#attr2_div').css({"visibility":"hidden", });}
            if (data.attr3_list[0] == 'すべて') {$('#attr3_div').css({"visibility":"hidden", });}
            if (data.attr4_list[0] == 'すべて') {$('#attr4_div').css({"visibility":"hidden", });}
            if (data.attr5_list[0] == 'すべて') {$('#attr5_div').css({"visibility":"hidden", });}
            $('#apply').click();
            data.attrs_name.forEach(function(elem, index) {
                console.log("attr"+ String(index+1)+"_label");
                document.getElementById("attr"+ String(index+1)+"_label").textContent = elem;
            });
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            console.log("ERROR:\n" +  textStatus + ":\n" + errorThrown);
        }
    });
  



    $('#apply').on('click', function() {
        if ($('#year').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        if ($('#month').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        if ($('#date').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        if ($('#time').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        if ($('#holyday').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        if ($('#yobi').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        if ($('#attr1').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        if ($('#attr2').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        if ($('#attr3').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        if ($('#attr4').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        if ($('#attr5').val().length == 0) { custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。'); return false;}
        $("#overlay").fadeIn(300);


        let request = {
          year: $('#year').val(),
          month: $('#month').val(),
          date: $('#date').val(),
          time: $('#time').val(),
          holyday: $('#holyday').val(),
          yobi: $('#yobi').val(),
          attr1: $('#attr1').val(),
          attr2: $('#attr2').val(),
          attr3: $('#attr3').val(),
          attr4: $('#attr4').val(),
          attr5: $('#attr5').val()
        };
        $.ajax({
          type: "POST",
          url: '/cgi-bin/mod_005.py',
          data: JSON.stringify(request),
          dataType: "json",
          success: function(data) {
            if (Object.keys(data).length  === 0) {
                custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。');
                return;
            }
            get_data = data;
            drawTrips();
          },
          error: function(XMLHttpRequest, textStatus, errorThrown) {
            setTimeout(function(){
                $("#overlay").fadeOut(300);
              },500);
              custom_alert('該当する条件でデータがありません。抽出条件を変えて更新してください。')
              console.log("ERROR:\n" +  textStatus + ":\n" + errorThrown);
          }
        }).done(function() {
            setTimeout(function(){
              $("#overlay").fadeOut(300);
            },500);
        });
      })
      
});

function getBoundingBox(data) {
    var bounds = {}, coords, point, latitude, longitude;
  
    for (var i = 0; i < data.features.length; i++) {
      coords = data.features[i].geometry.coordinates;
  
      for (var j = 0; j < coords.length; j++) {
        longitude = coords[j][0];
        latitude = coords[j][1];
        bounds.xMin = bounds.xMin < longitude ? bounds.xMin : longitude;
        bounds.xMax = bounds.xMax > longitude ? bounds.xMax : longitude;
        bounds.yMin = bounds.yMin < latitude ? bounds.yMin : latitude;
        bounds.yMax = bounds.yMax > latitude ? bounds.yMax : latitude;
      }
    }
  
    return bounds;
}


//CSV出力

function jsonToCsv(items) {
    // headerを取得
    const header = Object.keys(items[0]);
    const headerString = header.join(',');
  
    const replacer = (key, value) => value ?? '';
    const rowItems = items.map((row) =>
      header.map((fieldName) => JSON.stringify(row[fieldName], replacer)).join(',')
    );
  
    // headerとコンテンツ部分を結合する
    const csv = [headerString, ...rowItems].join('\r\n');
  
    return csv;
}

function csvexport(kind) {
    switch (kind) {
        case "a": data = df_data.df_selected; break;
        case "b": data = df_data.df_b; break;
        case "c": data = df_data.df_c; break;
        case "d": data = df_data.df_d; break;
        case "e": data = df_data.df_e; break;
        case "f": data = df_data.df_f; break;
        case "g": data = df_data.df_g; break;
        case "h": data = df_data.df_h; break;
        case "i": data = df_data.df_i; break;
        default : data = [];
    }
    
    if (data.length == 0 ) {
      alert("データが選択されていません");
      return 0;
    }
  
    csv_string = jsonToCsv(data)

    //ファイル名の指定
    let file_name   = "data_" + kind + ".csv";

    //CSVのバイナリデータを作る
    let blob        = new Blob([csv_string], {type: "text/csv"});
    let uri         = URL.createObjectURL(blob);

    //リンクタグを作る
    let link        = document.createElement("a");
    link.download   = file_name;
    link.href       = uri;

    //作ったリンクタグをクリックさせる
    document.body.appendChild(link);
    link.click();

    //クリックしたら即リンクタグを消す
    document.body.removeChild(link);

    delete link;
}


function drawTrips() {
    data = get_data;
    const interval = interval_timestamps(data);

    interval[0] -= ANIMATION_SPEED * INITIAL_PAUSE;

    document.getElementById("cowbell").min = interval[0]
    document.getElementById("cowbell").max = interval[1]

    document.getElementById("cowbell").value = interval[0]
    //const view = new deck.WebMercatorViewport({width: document.body.clientWidth, height: document.body.clientHeight});
    //座標変換を行うオブジェクトを生成する
    const view = new deck.WebMercatorViewport({
        width: document.getElementById("map").clientWidth,
        height: document.getElementById("map").clientHeight
    });
    const bb = bbox(data);
    //longitude = (bb[0][0] + bb[1][0]) / 2;
    //latitude = (bb[0][1] + bb[1][1]) / 2;

    const { longitude, latitude, zoom } = view.fitBounds(
        [
            [bb[0][0], bb[0][1]],
            [bb[1][0], bb[1][1]]
        ],
        {
            padding: 0 //地物を画面内に収める際に余白を設定する
        }
    );


    const deckgl = new deck.DeckGL({
        container: 'map',
        mapStyle: 'style/dark.json',
        initialViewState: {
          longitude: longitude, // 経度
          latitude: latitude,   // 緯度
          zoom: zoom,        // ズーム
        },
        controller: true,
        layers: []
      });


    const map = deckgl.getMapboxMap();
    map.addControl(new mapboxgl.ScaleControl({
        maxWidth: 160,
        unit: 'metric'
    }));
    //map.addControl(new mapboxgl.NavigationControl({ visualizePitch: true }), 'bottom-right');
    const RATE_ANIMATION_FRAME = 1;
    function animate() {
        time_ani = (time_ani + ANIMATION_SPEED/RATE_ANIMATION_FRAME) % (interval[1] - interval[0]);
        dd = new Date(time_ani + interval[0]);
        moment.locale("ja");
        formatted = moment.unix(dd).utc().format('YYYY年MM月DD日 HH時mm分ss秒 ');
    
        // var formatted = `
        //     ${dd.getFullYear()}/${(dd.getMonth()+1).toString().padStart(2, '0')}/${dd.getDate().toString().padStart(2, '0')} 
        //     ${dd.getHours().toString().padStart(2, '0')}:${dd.getMinutes().toString().padStart(2, '0')}:${dd.getSeconds().toString().padStart(2,'0')}
        //     `.replace(/\n|\r/g, '');
        document.getElementById("time_text").textContent = formatted;
        document.getElementById("cowbell").value = Math.trunc(time_ani+interval[0])
        req = window.requestAnimationFrame(animate);
    }

    
    //$('.mapboxgl-ctrl-zoom-in').click(function(event) {
    //
    //});

    setInterval(() => {
        deckgl.setProps({
            layers: [
                new deck.TripsLayer({
                    id: 'trips-layer',
                    data: data,
                    getPath: d => d.path,
                    getTimestamps: d => d.timestamps,
                    getColor: d => getColor(d.vendor),
                    visible: getVisible(0),
                    opacity: 1,
                    widthMinPixels: 5,
                    rounded: true,
                    trailLength: 100,
                    currentTime: time_ani + interval[0],
                    shadowEnabled: false
                }),
                new deck.ScatterplotLayer({
                    id: 'point-layer',
                    data: data,
                    opacity: 0.8,
                    radiusScale: 5,
                    radiusMinPixels: 1,
                    wrapLongitude: true,

                    getPosition: d => d.path[0],
                    getRadius: 5,
                    getFillColor: [255, 0, 0],

                    getFilterValue: d => d.timestamps[0],
                    filterRange: [time_ani + interval[0], time_ani + interval[0]+300000],
                    visible: getVisible(1),
                    extensions: [dataFilter],

                    pickable: false
                }),
                new deck.HeatmapLayer({
                    id: 'heatmapLayer',
                    data: data,
                    opacity: 0.8,

                    getPosition: d => d.path[0],
                    getRadius: 1,
                    getWeight: 1,
                    getFilterValue: d => d.timestamps[0],
                    filterRange: [time_ani + interval[0], time_ani + interval[0] + 300000],
                    visible: getVisible(2),
                    extensions: [dataFilter],
                    aggregation: 'SUM'
                })
            ]
        });
    }, 50);

    req = window.requestAnimationFrame(animate);
}


function end_inv() {
    window.cancelAnimationFrame(req)
}

function speedup() {
    ANIMATION_SPEED = ANIMATION_SPEED*10;
    ANIMATION_SPEED_SHOW = ANIMATION_SPEED_SHOW.times(10)
    document.getElementById("speed").textContent = "再生速度：" + ANIMATION_SPEED_SHOW + "倍";
}
function speeddown() {
    ANIMATION_SPEED = ANIMATION_SPEED*0.1;
    ANIMATION_SPEED_SHOW = ANIMATION_SPEED_SHOW.times(0.1)
    document.getElementById("speed").textContent = "再生速度：" + ANIMATION_SPEED_SHOW + "倍";
}

let range1 = document.getElementById("cowbell");
range1.addEventListener(`input`, function () {
    time_ani = range1.value - range1.min;
    time_ani = (time_ani + ANIMATION_SPEED/100) % (range1.max - range1.min);
    dd = new Date(time_ani + range1.min);
    moment.locale("ja");
    formatted = moment.unix(dd).utc().format('YYYY年MM月DD日 HH時mm分ss秒 ');

        // var formatted = `
        //     ${d.getFullYear()}/${(d.getMonth()+1).toString().padStart(2, '0')}/${d.getDate().toString().padStart(2, '0')} 
        //     ${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}:${d.getSeconds().toString().padStart(2,'0')}
        //     `.replace(/\n|\r/g, '');
    document.getElementById("time_text").textContent = formatted;
});
function custom_alert( message, title ) {
    if ( !title )
        title = 'メッセージ';

    if ( !message )
        message = 'No Message to Display.';

    $('<div></div>').html( message ).dialog({
        title: title,
        resizable: false,
        modal: true,
        buttons: {
            'Ok': function()  {
                $( this ).dialog( 'close' );
            }
        }
    });
}
function allselect() {
    $('#year').multiselect('selectAll', false);
    $('#month').multiselect('selectAll', false);
    $("#date").multiselect('selectAll', false);
    $("#time").multiselect('selectAll', false);
    $("#holyday").multiselect('selectAll', false);
    $("#yobi").multiselect('selectAll', false);
    $("#attr1").multiselect('selectAll', false);
    $("#attr2").multiselect('selectAll', false);
    $("#attr3").multiselect('selectAll', false);
    $("#attr4").multiselect('selectAll', false);
    $("#attr5").multiselect('selectAll', false);

}
function allreset() {
    $('#year').val([]);
    $('#month').val([]);
    $('#year').multiselect("refresh");
    $('#month').multiselect("refresh");

    $("#year").val($("#year").val().concat(initial_data.init_year)); 
    $('#year').multiselect("refresh");
    $("#month").val($("#month").val().concat(initial_data.init_month)); 
    $('#month').multiselect("refresh");

    $("#date").multiselect('selectAll', false);
    $("#time").multiselect('selectAll', false);
    $("#holyday").multiselect('selectAll', false);
    $("#yobi").multiselect('selectAll', false);
    $("#attr1").multiselect('selectAll', false);
    $("#attr2").multiselect('selectAll', false);
    $("#attr3").multiselect('selectAll', false);
    $("#attr4").multiselect('selectAll', false);
    $("#attr5").multiselect('selectAll', false);

}


