"use strict"

function importLayerPageInit (ctx) {

  var layerDepBtn = $("#add-layer-dependency-btn");
  var importAndAddBtn = $("#import-and-add-btn");
  var layerNameInput = $("#import-layer-name");
  var vcsURLInput = $("#layer-git-repo-url");
  var gitRefInput = $("#layer-git-ref");
  var layerDepInput = $("#layer-dependency");
  var layerNameCtrl = $("#layer-name-ctrl");
  var duplicatedLayerName = $("#duplicated-layer-name-hint");
  var localDirPath = $("#local-dir-path");

  var layerDeps = {};
  var layerDepsDeps = {};
  var currentLayerDepSelection;
  var validLayerName = /^(\w|-)+$/;

  /* Catch 'disable' race condition between type-ahead started and "input change" */
  var typeAheadStarted = 0;

  libtoaster.makeTypeahead(layerDepInput,
                           libtoaster.ctx.layersTypeAheadUrl,
                           { include_added: "true" }, function(item){
    currentLayerDepSelection = item;
    layerDepBtn.removeAttr("disabled");
    typeAheadStarted = 1;
  });

  layerDepInput.on("typeahead:select", function(event, data){
    currentLayerDepSelection = data;
  });

  // Disable local dir repo when page is loaded.
  $('#local-dir').hide();

  // disable the "Add layer" button when the layer input typeahead is empty
  // or not in the typeahead choices
  layerDepInput.on("input change", function(){
    if (0 == typeAheadStarted) {
      layerDepBtn.attr("disabled","disabled");
    }
    typeAheadStarted = 0;
  });

  /* We automatically add "openembedded-core" layer for convenience as a
   * dependency as pretty much all layers depend on this one
   */
  $.getJSON(libtoaster.ctx.layersTypeAheadUrl,
    { include_added: "true" , search: "openembedded-core" },
    function(layer) {
    if (layer.results.length > 0) {
      currentLayerDepSelection = layer.results[0];
        layerDepBtn.click();
    }
  });

  layerDepBtn.click(function(){
    typeAheadStarted = 0;
    if (currentLayerDepSelection == undefined)
      return;

    layerDeps[currentLayerDepSelection.id] = currentLayerDepSelection;

    /* Make a list item for the new layer dependency */
    var newLayerDep = $("<li><a></a><span class=\"glyphicon glyphicon-trash\" data-toggle=\"tooltip\" title=\"Remove\"></span></li>");

    newLayerDep.data('layer-id', currentLayerDepSelection.id);
    newLayerDep.children("span").tooltip();

    var link = newLayerDep.children("a");
    link.attr("href", currentLayerDepSelection.layerdetailurl);
    link.text(currentLayerDepSelection.name);
    link.tooltip({title: currentLayerDepSelection.tooltip, placement: "right"});

    var trashItem = newLayerDep.children("span");
    trashItem.click(function () {
      var toRemove = $(this).parent().data('layer-id');
      delete layerDeps[toRemove];
      $(this).parent().fadeOut(function (){
        $(this).remove();
      });
    });

    $("#layer-deps-list").append(newLayerDep);

    libtoaster.getLayerDepsForProject(currentLayerDepSelection.xhrLayerUrl,
                                      function (data){
        /* These are the dependencies of the layer added as a dependency */
        if (data.list.length > 0) {
          currentLayerDepSelection.url = currentLayerDepSelection.layerdetailurl;
          layerDeps[currentLayerDepSelection.id].deps = data.list;
        }

        /* Clear the current selection */
        layerDepInput.val("");
        currentLayerDepSelection = undefined;
        layerDepBtn.attr("disabled","disabled");
      }, null);
  });

  importAndAddBtn.click(function(e){
    e.preventDefault();
    /* This is a list of the names from layerDeps for the layer deps
     * modal dialog body
     */
    var depNames = [];

    /* arrray of all layer dep ids includes parent and child deps */
    var allDeps = [];

    /* temporary object to use to do a reduce on the dependencies for each
     * layer dependency added
     */
    var depDeps = {};

    /* the layers that have dependencies have an extra property "deps"
     * look in this for each layer and reduce this to a unquie object
     * of deps.
     */
    for (var key in layerDeps){
      if (layerDeps[key].hasOwnProperty('deps')){
        for (var dep in layerDeps[key].deps){
          var layer = layerDeps[key].deps[dep];
          depDeps[layer.id] = layer;
        }
      }
      depNames.push(layerDeps[key].name);
      allDeps.push(layerDeps[key].id);
    }

    /* we actually want it as an array so convert it now */
    var depDepsArray = [];
    for (var key in depDeps)
      depDepsArray.push (depDeps[key]);

    if (depDepsArray.length > 0) {
      var layer = { name: layerNameInput.val(), url: "#", id: -1 };
      var title = "Layer";
      var body = "<strong>"+layer.name+"</strong>'s dependencies ("+
        depNames.join(", ")+"</span>) require some layers that are not added to your project. Select the ones you want to add:</p>";

      showLayerDepsModal(layer,
                         depDepsArray,
                         title, body, false, function(layerObsList){
        /* Add the accepted layer dependencies' ids to the allDeps array */
        for (var key in layerObsList){
          allDeps.push(layerObsList[key].id);
        }
        import_and_add ();
      });
    } else {
      import_and_add ();
    }

    function import_and_add () {
      /* convert to a csv of all the deps to be added */
      var layerDepsCsv = allDeps.join(",");

      var layerData = {
        name: layerNameInput.val(),
        vcs_url: vcsURLInput.val(),
        git_ref: gitRefInput.val(),
        dir_path: $("#layer-subdir").val(),
        project_id: libtoaster.ctx.projectId,
        layer_deps: layerDepsCsv,
        local_source_dir: $('#local-dir-path').val(),
        add_to_project: true,
      };

      if ($('input[name=repo]:checked').val() == "git") {
        layerData.local_source_dir = "";
      } else {
        layerData.vcs_url = "";
        layerData.git_ref = "";
      }

      $.ajax({
          type: "PUT",
          url: ctx.xhrLayerUrl,
          data: JSON.stringify(layerData),
          headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
          success: function (data) {
            if (data.error != "ok") {
              console.log(data.error);
              /* let the user know why nothing happened */
              alert(data.error)
            } else {
              createImportedNotification(data);
              window.location.replace(libtoaster.ctx.projectPageUrl);
            }
          },
          error: function (data) {
            console.log("Call failed");
            console.log(data);
          }
      });
    }
  });

  /* Layer imported notification */
  function createImportedNotification(imported){
    var message = "Layer imported";

    if (imported.deps_added.length === 0) {
      message = "You have imported <strong><a class=\"alert-link\" href=\""+imported.imported_layer.layerdetailurl+"\">"+imported.imported_layer.name+"</a></strong> and added it to your project.";
    } else {

      var links = "<a href=\""+imported.imported_layer.layerdetailurl+"\">"+imported.imported_layer.name+"</a>, ";

      imported.deps_added.map (function(item, index){
        links +='<a href="'+item.layerdetailurl+'">'+item.name+'</a>';
        /*If we're at the last element we don't want the trailing comma */
        if (imported.deps_added[index+1] !== undefined)
          links += ', ';
      });

      /* Length + 1 here to do deps + the imported layer */
      message = 'You have imported <strong><a href="'+imported.imported_layer.layerdetailurl+'">'+imported.imported_layer.name+'</a></strong> and added <strong>'+(imported.deps_added.length+1)+'</strong> layers to your project: <strong>'+links+'</strong>';
    }

    libtoaster.setNotification("layer-imported", message);
  }

  function enable_import_btn(enabled) {
    var importAndAddHint = $("#import-and-add-hint");

    if (enabled) {
      importAndAddBtn.removeAttr("disabled");
      importAndAddHint.hide();
      return;
    }

    importAndAddBtn.attr("disabled", "disabled");
    importAndAddHint.show();
  }

  function check_form() {
    var valid = false;
    var inputs = $("input:required");
    var inputStr = inputs.val().split("");

    for (var i=0; i<inputs.val().length; i++){
      if (!(valid = inputStr[i])){
        enable_import_btn(false);
        break;
      }
    }

    if (valid) {
      if ($("#local-dir-radio").prop("checked") &&
          localDirPath.val().length > 0) {
        enable_import_btn(true);
      }

      if ($("#git-repo-radio").prop("checked")) {
        if (gitRefInput.val().length > 0 &&
            gitRefInput.val() == 'HEAD') {
          $('#invalid-layer-revision-hint').show();
          $('#layer-revision-ctrl').addClass('has-error');
          enable_import_btn(false);
        } else if (vcsURLInput.val().length > 0 &&
                   gitRefInput.val().length > 0) {
          $('#invalid-layer-revision-hint').hide();
          $('#layer-revision-ctrl').removeClass('has-error');
          enable_import_btn(true);
        }
      }
    }

    if (inputs.val().length == 0)
      enable_import_btn(false);
  }

  function layerExistsError(layer){
    var dupLayerInfo = $("#duplicate-layer-info");

    if (layer.local_source_dir) {
      $("#git-layer-dup").hide();
      $("#local-layer-dup").fadeIn();
      dupLayerInfo.find(".dup-layer-name").text(layer.name);
      dupLayerInfo.find(".dup-layer-link").attr("href", layer.layerdetailurl);
      dupLayerInfo.find("#dup-local-source-dir-name").text(layer.local_source_dir);
    } else {
      $("#git-layer-dup").fadeIn();
      $("#local-layer-dup").hide();
      dupLayerInfo.find(".dup-layer-name").text(layer.name);
      dupLayerInfo.find(".dup-layer-link").attr("href", layer.layerdetailurl);
      dupLayerInfo.find("#dup-layer-vcs-url").text(layer.vcs_url);
      dupLayerInfo.find("#dup-layer-revision").text(layer.vcs_reference);
    }
    $(".fields-apart-from-layer-name").fadeOut(function(){

      dupLayerInfo.fadeIn();
    });
  }

  layerNameInput.on('blur', function() {
    if (!$(this).val()){
      return;
    }
    var name = $(this).val();

    /* Check if the layer name exists */
    $.getJSON(libtoaster.ctx.layersTypeAheadUrl,
        { include_added: "true" , search: name, format: "json" },
        function(layer) {
          if (layer.results.length > 0) {
            for (var i in layer.results){
              if (layer.results[i].name == name) {
                layerExistsError(layer.results[i]);
              }
            }
          }
      });
  });

  vcsURLInput.on('input', function() {
    check_form();
  });

  gitRefInput.on('input', function() {
    check_form();
  });

  layerNameInput.on('input', function() {
    if ($(this).val() && !validLayerName.test($(this).val())){
      layerNameCtrl.addClass("has-error")
      $("#invalid-layer-name-hint").show();
      enable_import_btn(false);
      return;
    }

    if ($("#duplicate-layer-info").css("display") != "None"){
      $("#duplicate-layer-info").fadeOut(function(){
      $(".fields-apart-from-layer-name").show();
      radioDisplay();
    });

  }

    radioDisplay();

    /* Don't remove the error class if we're displaying the error for another
     * reason.
     */
    if (!duplicatedLayerName.is(":visible"))
      layerNameCtrl.removeClass("has-error")

    $("#invalid-layer-name-hint").hide();
    check_form();
  });

  /* Setup 'blank' typeahead */
  libtoaster.makeTypeahead(gitRefInput,
                           ctx.xhrGitRevTypeAheadUrl,
                           { git_url: null }, function(){});


  vcsURLInput.focusout(function (){
    if (!$(this).val())
      return;

    /* If we a layer name specified don't overwrite it or if there isn't a
     * url typed in yet return
     */
    if (!layerNameInput.val() && $(this).val().search("/")){
      var urlPts = $(this).val().split("/");
      /* Add a suggestion of the layer name */
      var suggestion = urlPts[urlPts.length-1].replace(".git","");
      layerNameInput.val(suggestion);
    }

    /* Now actually setup the typeahead properly with the git url entered */
    gitRefInput._typeahead('destroy');

    libtoaster.makeTypeahead(gitRefInput,
                             ctx.xhrGitRevTypeAheadUrl,
                             { git_url: $(this).val() },
                             function(selected){
                               gitRefInput._typeahead("close");
                             });

  });

  function radioDisplay() {
    if ($('input[name=repo]:checked').val() == "local") {
      $('#git-repo').hide();
      $('#import-git-layer-and-add-hint').hide();
      $('#local-dir').fadeIn();
      $('#import-local-dir-and-add-hint').fadeIn();
    } else {
      $('#local-dir').hide();
      $('#import-local-dir-and-add-hint').hide();
      $('#git-repo').fadeIn();
      $('#import-git-layer-and-add-hint').fadeIn();
    }
  }

  $('input:radio[name="repo"]').change(function() {
    radioDisplay();
    if ($("#local-dir-radio").prop("checked")) {
      if (localDirPath.val().length > 0) {
        enable_import_btn(true);
      } else {
        enable_import_btn(false);
      }
    }
    if ($("#git-repo-radio").prop("checked")) {
      if (vcsURLInput.val().length > 0 && gitRefInput.val().length > 0) {
        enable_import_btn(true);
      } else {
        enable_import_btn(false);
      }
    }
  });

  localDirPath.on('input', function(){
    if ($(this).val().trim().length == 0) {
      $('#import-and-add-btn').attr("disabled","disabled");
      $('#local-dir').addClass('has-error');
      $('#hintError-dir-abs-path').show();
      $('#hintError-dir-path-starts-with-slash').show();
    } else {
      var input = $(this);
      var reBeginWithSlash = /^\//;
      var reCheckVariable = /^\$/;
      var re = /([ <>\\|":%\?\*]+)/;

      var invalidDir = re.test(input.val());
      var invalidSlash = reBeginWithSlash.test(input.val());
      var invalidVar = reCheckVariable.test(input.val());

      if (!invalidSlash && !invalidVar) {
        $('#local-dir').addClass('has-error');
        $('#import-and-add-btn').attr("disabled","disabled");
        $('#hintError-dir-abs-path').show();
        $('#hintError-dir-path-starts-with-slash').show();
      } else if (invalidDir) {
        $('#local-dir').addClass('has-error');
        $('#import-and-add-btn').attr("disabled","disabled");
        $('#hintError-dir-path').show();
      } else {
        $('#local-dir').removeClass('has-error');
        if (layerNameInput.val().length > 0) {
          $('#import-and-add-btn').removeAttr("disabled");
        }
        $('#hintError-dir-abs-path').hide();
        $('#hintError-dir-path-starts-with-slash').hide();
        $('#hintError-dir-path').hide();
      }
    }
  });
}
