window.onload = APPStart;

var known_paths = [];
var path_ui_nr = 0;
var modal_dirs = [];

// Page onload event handler
function APPStart() {
    state = false;
    guid_id = "<!---PEER_HASH--->";
    max_paths = <!---PATHS_MAX--->;
    version_string = "<!---VERSION--->";

    $(document).ready(function(){
        // keep it for later with different id
        //$('#peer_page').load('peer_page.html');

        if ("WebSocket" in window) {
            // using something from other js - seems fine
            var ws = new FancyWebSocket("ws://<!---WEBSOCKET_ADDR--->:<!---PORT_WEBSOCKET--->/ws");

            // the usual suspects
            ws.bind('open', function(){
                $('#statusMessage').text("connected");
                ws.send('ready');
                // register hash UUID
            });
            ws.bind('close', function(){
                gracefullyClose();
            });

            ws.bind('init_paths', function(data){
               for(let i = 0; i < data.length; i++){
                  addModalPathSelector(data[i]);
               }
            });

            ws.bind('start', function(data){
               showPath(data);
            });

            ws.bind('searching', function(data){
               spinPath(data);
            });

            ws.bind('update', function(data){
               updateNetView(data);
            });

            ws.bind('rest_dirs', function(data){
               onRESTDir(data);
            });

            window.onbeforeunload = function(event) {
               socket.close();
            };


            // dealing with accordion
            var Accordion = function(el, multiple) {
                this.el = el || {};
                this.multiple = multiple || false;

                var links = this.el.find('.link');

                links.on('click', {el: this.el, multiple: this.multiple}, this.dropdown)
            }
            Accordion.prototype.dropdown = function(e) {
                var $el = e.data.el;
                $this = $(this),
                $next = $this.next();

                $next.slideToggle();
                $this.parent().toggleClass('open');

                if (!e.data.multiple) {
                    $el.find('.submenu').not($next).slideUp().parent().removeClass('open');
                };
            }
            var accordion = new Accordion($('#accordion'), false);

            // click accordion.div.div to show first entry!!
            $("#accordion div div").click();

            // modal button events
            $('#modal_add').click(function() {
                handle_path_add_button();
            });
            $('#modal_sub').click(function(){
                handle_path_sub_button();
            });
            $('#modal_close').click(function(){
                ws.send('start', modal_dirs);
            });
            // dynamic content problem
            $('#modal_path_table').on('click', 'div > button.dirDropper',  function(event){
              //event.preventDefault();
              event.stopPropagation();
              // read nr from suffix
              let splitter = this.id.split("_")[1];
              let nr = parseInt(splitter);
              ws.send('rest_dir', {'nr': nr, 'dir': modal_dirs[nr]});
              this.dropdown('dispose');
            });

            // enable html tooltips
            $('body').tooltip({
                selector: '.html_tooltip'
            });

            // STARTUP with modal
            $('#modal_dir_chooser').modal('show');
        } else {
            // The browser doesn't support WebSocket
            alert("WebSocket NOT supported by your Browser!");
        }
    });
}

function spinPath(data) {
    let on_off = data[1];

    if (data[0].type === 'net') {
       let spinner = $('#host_search_progress').find('span');

       if (on_off === true) {
           spinner.removeClass('d-none');
       } else {
           setTimeout(_ => spinner.addClass('d-none'), 100);
       }
    } else {
        let path_nr = data[0].cnt.nr
        let spinner = $('#path_obj' + path_nr).find('span');

        if (on_off === true) {
            spinner.removeClass('d-none');
        } else {
            spinner.addClass('d-none');
            spinner.replaceWith( "<svg width='1em' height='1em' viewBox='0 0 16 18'"
                               + " class='bi bi-circle-fill' fill='currentColor'"
                               + " xmlns='http://www.w3.org/2000/svg'>"
                               + " <circle cx='8' cy='8' r='8'/></svg>");
        }
    }
}

function showPath(data) {
    // encapsulate paths json
    let paths = data.paths;

    let path_len = paths.length;
    for (let i=0; i < path_len; i++) {
        let path_nr = paths[i].nr;
        // register for graceful closing
        known_paths.push(path_nr);
        let obj_id =  "path_obj" + path_nr;
        // create obj
        let new_el_html = "<tr id='" + obj_id + "'><td class='col-xs-3 text-monospace' style='width: 90%'>"
                         + helper_win_canonical(paths[i].name) + "</td><td>"
                         +"<span class='d-none spinner-grow spinner-grow-sm col-xs-3 text-right' role='status' aria-hidden='true'></span>"
                         + "</td></tr>";
        new_el = $.parseHTML(new_el_html);
        // append it as an object but wait since div creation need little time
        $("#paths_searched").append(new_el);
    }
}

function updateNetView(data) {
    if (data.view === 'add') {
        let peer_id = data.cnt.id;
        let addresses = data.cnt.addr;

        let obj_id =  "host_obj_" + peer_id;
        // tooltip is the multi-address for that peer
        let tooltip = "";
        for(let i = 0; i < addresses.length; i++){
            tooltip += "=" + addresses[i] + "=";
        }
        // create obj
        let new_el_html =  '<tr id="' + obj_id + '" '
                         + 'data-toggle="tooltip" data-placement="bottom" data-html="true" '
                         + 'title="Adresses: '
                         + tooltip
                         + '"><td class="col-xs-3">'
                         + '<button id="netbutton_' + peer_id + '" class="btn btn-light text-monospace" '
                         + 'value="' + guid_id + '"'
                         + 'onClick="netButtonClick(this.id, this.value)">'
                         + peer_id
                         + '</button>'
                         + '</td><td id="result_' + peer_id + '">'
                         + '<div class="spinner-border spinner-border-sm" role="status">'
                         + ' <span class="sr-only"></span>'
                         + '</div>'
                         + '</td></tr>';
        new_el = $.parseHTML(new_el_html);
        // append it as an object
        $("#found_peers").append(new_el);
        $('#' + obj_id).hide().fadeIn(500);
    }
    else if (data.view === 'remove') {
        // delete object
        let peer_id = data.cnt;

        let obj_id =  "host_obj_" + peer_id;
        $('#' + obj_id).fadeOut(1500).remove();
    }
    else if (data.view === 'finished') {
        let peer_id = data.cnt.peer;
        if (peer_id === guid_id) {
            // myself
            let new_el = html_build_finished_peer(data.cnt.data);
            // set text in peer_page
            $('#own_finished').html(new_el);
            // set tooltip
            $('#own_header').attr('title',new_el);
        } else {
            // foreign peer results
            let new_el = html_build_finished_peer(data.cnt.data);
            let first_result = data.cnt.data.nr_found_songs;
            let new_text =  '<div class="col-xs-3 html_tooltip" data-toggle="tooltip" data-placement="right" data-html="true"'
                          + '     title="' + new_el + '">' + first_result + ' audio files found </div>';
            $('#result_' + peer_id + ' div').replaceWith(new_text);
        }
    }
    else {
        console.log("The view '" + data.view + "' is not implemented yet!");
    }
}

function gracefullyClose() {
      // stop host spinner
      let spinnerSearchHost = $('#host_search_progress').find('span');
      spinnerSearchHost.addClass('d-none');
      // stop path spinners
      for (let i=0; i < known_paths.length; i++) {
          let spinnerPath = $('#path_obj' + known_paths[i]).find('span');
          spinnerPath.addClass('d-none');
      }

      $('#statusMessage').text("not connected");
      document.getElementById("overlay").style.display = "block";
}

function netButtonClick(button_peer, guid) {
    // get frame (table id)
    let peer = button_peer.split("_")[1];

    // if exists go back
    if ($("#frame_" + peer).length)
        return


    // collapse old entry
    $("#frame_"+peer).collapse('toggle');

    // create entry
    let new_foreign_row = '<div id="frame_' + peer + '"><div class="link rounded">Foreign: ' + peer
                        + '</div><div class="submenu" id="page_' + peer +  '"></div></div>';
    $("#accordion").append(new_foreign_row);
}

function addModalPathSelector(path_name) {
    let name = "home";
    if (path_name === undefined) {
        path_name = "";
    } else {
        name = helper_extractLastDir(path_name);
    }
    modal_dirs[path_ui_nr] = path_name;
    let path_string = ('0' + path_ui_nr).slice(-2);
    let new_selector =  '  <div id="dropdowndiv_' + path_string + '" class="dropdown" style="padding: 5px;">'
                      + '   <button class="btn btn-secondary dropdown-toggle dirDropper" id="dropmenu_' + path_string + '"'
                      + '           data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"'
                      + '           style="max-height:50vh; overflow-y:auto;"'
                      + '   ><i>' + name + '</i><span class="sr-only">(current)</span></button>'
                      + '   <div id="dropdown_' + path_string + '"'
                      + '        class="dropdown-menu" aria-labelled-by="dropdownMenuButton"'
                      + '        style="transform: translate3d(0px,0px,0px);">'
                      + '   </div>'
                      + '  </div>';
    $("#modal_path_table").append(new_selector);
    // increase counter for new selector
    path_ui_nr += 1;
}

function onRESTDir(data) {
  // stop path spinners
  let nr = data.nr;
  let dirs_len = data.dirs.length;

  let path_string = ('0' + nr).slice(-2);
  let dropdown_menu = $("#dropdown_" + path_string);
  // trick: avoid that very first item often is above content
  //        in a bit longer lists by adding a divider ;-)
  dropdown_menu.append(' <div class="dropdown-divider"></div>')
  for (let i=0; i < dirs_len; i++) {
      let name = "";
      if (i === 0) {
         // first entry can be the ".." directory
         if (dirs_len > 1) {
            // if 1st is completly contained in the 2nd, then it's the ".."
            if (data.dirs[1].includes(data.dirs[0])) {
                // hide parent as ".."
                name = "..";
            } else {
                name = helper_extractLastDir(data.dirs[0]);
            }
         } else {
            // it's not always the ".."
            if (modal_dirs[nr].includes(data.dirs[0])) {
                name = "..";
            } else {
                name = helper_extractLastDir(data.dirs[0]);
            }
         }
      } else {
         name = helper_extractLastDir(data.dirs[i]);
      }
      let new_link =  '     <a class="dropdown-item" href="#"'
                    + '       onClick="uiUpdateDropMenu(' + nr + ',\'' + encodeURIComponent(data.dirs[i]) + '\');"'
                    + '      >' + name + '</a>';
      dropdown_menu.append(new_link);
      dropdown_menu.dropdown('update');
      dropdown_menu.dropdown('toggle');
  }
}

function uiUpdateDropMenu(nr, new_dir) {
    let path_string = ('0' + nr).slice(-2);
    let decode_dir = decodeURIComponent(new_dir);
    // update title
    $("#dropmenu_" + path_string).html(helper_extractLastDir(decode_dir) + '<span class="caret"></span>');
    modal_dirs[nr] = decode_dir;
    // remove old entries
    $("#dropdown_" + path_string).children().remove();
}

function handle_path_add_button() {
    if (path_ui_nr < max_paths) {
        addModalPathSelector(undefined);
        // grey out if end is reached
        if (path_ui_nr === max_paths) {
            $('#modal_add').prop('disabled',true).css('opacity',0.5);
        }
        // validate sub button
        $('#modal_sub').prop('disabled',false).css('opacity',1.0);
    }
}

function handle_path_sub_button() {
    if (path_ui_nr > 0) {
        path_ui_nr -= 1;
        modal_dirs.pop();
        let path_string = ('0' + path_ui_nr).slice(-2);
        $("#dropdowndiv_" + path_string).remove();
        if (path_ui_nr === 1) {
            $('#modal_sub').prop('disabled',true).css('opacity',0.5);
        }
        $('#modal_add').prop('disabled',false).css('opacity',1.0);
    }
}

function html_build_finished_peer(data) {
    let searched_files = data.nr_searched_files;
    let found_audio = data.nr_found_songs;
    let duplicates = data.nr_internal_duplicates;
    let size_data = data.size_of_data_in_kb;
    let html =   'files searched      :<b>' + searched_files + '</b><br/>'
               + 'audio files analyzed:<b>' + found_audio + '</b><br/>'
               + 'duplicates          :<b>' + duplicates + '</b><br/>'
               + '<b>' + size_data + ' kb</b> of data to network';
//    let html =   '<div><b>files searched:</b>' + searched_files + '</div>';
    return html;
}

function helper_extractLastDir(dir_path) {
    // should be platform independent, but's I can't check all,
    // especially windows first "canonical" form is difficult
    return dir_path.split(/.*[\/|\\]/)[1];
}

function helper_win_canonical(dir_path) {
    // clear of \\?\ prefix in windows
    // https://stackoverflow.com/questions/50322817/how-do-i-remove-the-prefix-from-a-canonical-windows-path
    // from rust but to be displayed nicely
    return dir_path.replace(/\\\\\?\\/g, '');
}
