import cytoscape from 'cytoscape';
import $ from "jquery";
import 'jquery-ui-dist/jquery-ui';
import EditorActionsManager from "../managers/EditorActionsManager";


export default class DragDropNodeAddPlugin {



    pathwayHandler: (pathwayName: string) => void;

    private cy: any;
    private editor: EditorActionsManager;

    constructor(editor: EditorActionsManager, cy: any, pathwayHandler: (pathwayName: string) => void)
    {
      this.editor = editor;
      this.cy = cy;
      this.pathwayHandler = pathwayHandler;
      this.initNodeAdd();
    }

    //TODO JQUERY IS IGNORED
    initNodeAdd()
    {
      var nodeAddClass = this;
      var defaults = {
        height: 30,   //height of the icon container
        width: 30,    //width of the icon container
        padding: 5,  //padding of the icon container(from right & top)
        backgroundColorDiv: '#fbfbfb',   //background color of the icon container
        borderColorDiv: '#fff',    //border color of the icon container
        borderWidthDiv: '0px',    //border width of the icon container
        borderRadiusDiv: '5px',    //border radius of the icon container

        icon: '',   //icon class name

        nodeParams: function(){
          // return element object to be passed to cy.add() for adding node
          return {};
        }
      };

      const self = this;

      // @ts-ignore
      $.fn.cytoscapeNodeadd = function(params: any) {
        var options = $.extend(true, {}, defaults, params);
        var fn = params;

        var functions = {
          destroy: function() {
            var $this = $(this);

            $this.find(".ui-cytoscape-nodeadd").remove();
          },
          init: function()
          {
            return $(this).each(function()
            {
              var components = options.components;
              for (const component of components)
              {
                var dragContainer = component.container;
                //var explanationText = component.explanationText;

                var $nodeadd = $('<div class="ui-cytoscape-nodeadd"></div>');
                dragContainer.append($nodeadd);
                var $nodeDragHandle = $('<div class="ui-cytoscape-nodeadd-nodediv"> \
                                                <span id="ui-cytoscape-nodeadd-icon" class="draggable" nodeType="'+ component.nodeType +'">\
                                                  <img src="'+component.icon+'"</img>\
                                                </span>\
                                              </div>');
                $nodeadd.append($nodeDragHandle);

                $nodeDragHandle.bind("mousedown", function(e: any)
                {
                  e.stopPropagation(); // don't trigger dragging of nodeadd
                  e.preventDefault(); // don't cause text selection
                });

                //Setup UI
                dragContainer.find(".ui-cytoscape-nodeadd-nodediv").css({
                  background: options.backgroundColorDiv,
                  border: options.borderWidthDiv + ' solid ' + options.borderColorDiv,
                  'border-radius': options.borderRadiusDiv
                });

                //Init Draggable
                dragContainer.find("#ui-cytoscape-nodeadd-icon").draggable({
                  helper: "clone",
                  cursor: "pointer"
                });
              }

              // @ts-ignore TODO: AMENDMENT ATTENTION
              var $container = $(this);
              //Init Droppable
              // @ts-ignore TODO: Droppable is ignored
              $container.droppable({
                activeClass: "ui-state-highlight",
                // accept: "#ui-cytoscape-nodeadd-icon",
                drop: function(event: any, ui: any) {
                  $container.removeClass("ui-state-highlight");

                  var currentOffset = $container.offset();
                  var relX = event.pageX - currentOffset.left;
                  var relY = event.pageY - currentOffset.top;

                  var nodeType = $(ui.helper).attr('nodeType').toUpperCase();

                  var cy = nodeAddClass.cy;

                  //Hold a map for parents and candidate parent nodes for this addition
                  var nodeMap = {};
                  var parentMap = {};
                  //Loop through nodes for hit testing about drag position on canvas
                  cy.nodes().forEach(function(node: any)
                  {
                    var nodeBbox = node.renderedBoundingBox();
                    //Rectangle point test
                    if ( (relX <= nodeBbox.x2 && relX >= nodeBbox.x1) && (relY <= nodeBbox.y2 && relY >= nodeBbox.y1) && node.data().type != 'GENE' )
                    {
                      //If node has a children put an entry to the parentMap
                      if (node.children().length > 0)
                      {
                        parentMap[node.id()] = true;
                      }

                      //If parent of this node is already added to the node map remove it, since our candidate is in deeper level !
                      if (parentMap[node._private.data.parent])
                      {
                        delete nodeMap[node._private.data.parent];
                      }

                      //Add an entry to node map
                      nodeMap[node.id()] = node;
                    }
                  });

                  //Check if any parent found, if so set parent field
                  var parent = nodeMap[Object.keys(nodeMap)[0]];
                  var nodeData = {w: "0", h: "100", parent: 0, type: nodeType, name:'New '+ $(ui.helper).attr('nodeType')};
                  if (parent)
                  {
                    if(parent.data().type == "FAMILY" || parent.data().type == "COMPLEX")
                    {
                      if(nodeType != "COMPARTMENT" && nodeType != "PROCESS")
                      {
                        nodeData.parent = parent.id();
                      }
                    }
                    else
                    {
                      nodeData.parent = parent.id();
                    }
                  }
                  if (nodeType === "PROCESS") {
                    nodeData.w = "100";
                    nodeData.h = "35";
                  }
                  else {
                    nodeData.w = "150";
                    nodeData.h = "52";
                  }

                  //Adjust position according to the zoom level and pan !
                  //To set rendered position !!!
                  //TODO refactor this !
                  relX = relX / cy.zoom() + cy.extent().x1;
                  relY = relY / cy.zoom() + cy.extent().y1;
                  nodeAddClass.editor.addNode(nodeData,{x: relX,y: relY});
                  self.pathwayHandler("Additional Pathway");

                }
              });

            });
          }
        };

        if (functions[fn]) {
          return functions[fn].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof fn == 'object' || !fn) {
          return functions.init.apply(this, arguments);
        } else {
          $.error("No such function `" + fn + "` for jquery.cytoscapenodeadd");
        }

        return $(this);
      };

      // @ts-ignore
      $.fn.cynodeadd = $.fn.cytoscapeNodeadd;
      try{
      /* Adding as an extension to the core functionality of cytoscape.js*/
      cytoscape('core', 'nodeadd', function(options: any) {

        // @ts-ignore
        $(this.container()).cytoscapeNodeadd(options);
      });
      } catch(err){
        console.log(err);
      }
    }




}
