/**
 * This files contain wrappers methods calling angular-style scope methods; the
 * wrappers use one JQuery call to identify a "root" HTML element (the one that
 * instantiates the SedController), retrieving the is angular-style scope and
 * call its methods. These wrappers cannot be used by RINA (RINA is angular,
 * wrappers are JQuery) but they are needed by MET
 */
var LOCAL_MET_COMMON_JS = true;

function getFormDataFull(craftEnum)
{
	var rootHtmlElem = SedForm.getRootHtmlElem();
	var scope = angular.element(rootHtmlElem).scope();
	return scope.getFormDataFull(craftEnum);
}

function getFormData(craftEnum)
{
	var rootHtmlElem = SedForm.getRootHtmlElem();
	var scope = angular.element(rootHtmlElem).scope();
	return scope.getFormData(craftEnum);
}

function getFormDataAsString(craftEnum)
{
	var rootHtmlElem = SedForm.getRootHtmlElem();
	var scope = angular.element(rootHtmlElem).scope();
	return scope.getFormDataAsString(craftEnum);
}

function setFormDataMET(sedAsJsonString, craftEnum)
{
	if (sedAsJsonString != null)
		setFormData(sedAsJsonString, craftEnum);
	return "OK";
}

function setFormData(sedAsJsonString, craftEnum)
{
	if (sedAsJsonString == null)
		Utils.assertFailed("Parameter sedAsJsonString should be not null");

	var rootHtmlElem = SedForm.getRootHtmlElem();
	var inputModel = angular.fromJson(sedAsJsonString);
	var scope = angular.element(rootHtmlElem).scope();
	scope.$apply(function()
	{
		scope.setFormData(inputModel, craftEnum);
	});

}

function clearFormData()
{
	var rootHtmlElem = SedForm.getRootHtmlElem();
	var scope = angular.element(rootHtmlElem).scope();

	scope.$apply(function()
	{
		//scope.clearFormData();
		scope.showErrors('None');
	});

}

function validateFormData(bValidateAsDraft)
{
	var rootHtmlElem = SedForm.getRootHtmlElem();
	var scope = angular.element(rootHtmlElem).scope();

	scope.$apply(function()
	{
		if (bValidateAsDraft)
			//scope.validateFormDataAsDraft();
			scope.showErrors('DRAFT');
		else 
			//scope.validateFormDataRegular();
			scope.showErrors('FULL');
	});
	
	if(scope.errors.length > 0) {
		var returnValue = "";
		
		for(var i=0; i<scope.errors.length; i++ ) {
			returnValue = returnValue.concat(scope.errors[i].message);
			
			if(i != scope.errors.length - 1)
				returnValue = returnValue.concat(';');
		}
		
		return returnValue;
	}
}

function validateFormDataAsDraftWarnings()
{
	var rootHtmlElem = SedForm.getRootHtmlElem();
	var scope = angular.element(rootHtmlElem).scope();

	scope.$apply(function()
	{
		//scope.validateFormDataAsDraftWarnings();
		scope.showErrors('NON_DRAFT_AS_WARNING');
	});
	
	if(scope.errors.length > 0) {
		var returnValue = "";
		
		for(var i=0; i<scope.errors.length; i++ ) {
			returnValue = returnValue.concat(scope.errors[i].message);
			
			if(i != scope.errors.length - 1)
				returnValue = returnValue.concat(';');
		}
		
		return returnValue;
	}
}

function getMetaModel()
{
	var rootHtmlElem = SedForm.getRootHtmlElem();
	var scope = angular.element(rootHtmlElem).scope();
	return scope.getMetaModel();
}

window.onload = function()
{
	var printSection = document.createElement('div');
	printSection.id = 'printSection';
	document.body.appendChild(printSection);
}

/*
window.onafterprint = function () {
	// clean the print section before adding new content
	console.log('AAA');
	printSection.innerHTML = '';
};
*/

function printForm()
{
	var title = SedForm.getTitle();
	var rootHtmlElem = SedForm.getRootHtmlElem();
	var scope = angular.element(rootHtmlElem).scope();
	
	//console.log(angular.element(rootHtmlElem).html());
	//console.log(angular.element(rootHtmlElem)[0]);
	
	scope.printFormMET(angular.element(rootHtmlElem)[0], title);
	
	/*
	 $timeout(function () {
		 printElement(angular.element(rootHtmlElem)[0]);
       }, 1000);
	 
	//printElement(angular.element(rootHtmlElem)[0]);
	*/
}

function SedForm()
{
	// we need this solely for eclipse outline to put everything under Test,
	// otherwise we would have two items in the outline
	this._dummy = null;
}

SedForm.LOG =
{
	text : ""
};

SedForm.getRootHtmlElem = function()
{
	var rootHtmlElem = document.querySelector("[ng-controller='SedController']");

	if (rootHtmlElem == null)
		Utils
			.assertFailed("Cannot find the SED form's root element (containing attribute ng-controller='SedController'). This should be part of the form-template");

	return rootHtmlElem;
}

SedForm.getTitle = function()
{
	var rootHtmlElem = document.querySelector("[class='sedHeading']");

	if (rootHtmlElem == null)
		rootHtmlElem = document.querySelector("[class='sedHeadingAC']");
	
	if (rootHtmlElem == null)
		Utils
			.assertFailed("Cannot find the SED Angular form's root element (containing attribute class='sedHeading' or class='sedHeadingAC'). This should be part of the form-template");

	return rootHtmlElem;
}

SedForm.getFooterHtmlElem = function()
{
	var footerHtmlElem = document.querySelector("[ng-controller='FooterController']");

	if (footerHtmlElem == null)
		Utils
			.assertFailed("Cannot find the SED form's footer element (containing attribute ng-controller='FooterController'). This should be part of the form-template");

	return footerHtmlElem;
}

SedForm.safeApply = function()
{
	var rootHtmlElem = SedForm.getRootHtmlElem();
	var scope = angular.element(rootHtmlElem).scope();
	if (scope == null)
		return;
	var phase = scope.$root.$$phase;
	if (phase != "$apply" && phase != "$digest")
		scope.$apply();
}

SedForm.out = function(sText)
{
	SedForm.LOG.text = sText;
	SedForm.safeApply();
}

SedForm.log = function(sText)
{
	SedForm.LOG.text += sText;
	SedForm.safeApply();
}

SedForm.logln = function(sText)
{
	SedForm.LOG.text += sText + "\n";
	SedForm.safeApply();
}

// ////////////////////////////////////////////////////////
// SequenceGen
// ////////////////////////////////////////////////////////
/**
 * used for allocating an unique sequence-id to any Item object that is created.
 * This is useful in debugging ensuring a immutable reference of an object (a
 * role hold by an mem-address in C/C++)
 */
function SequenceGen()
{
	this._dummy = null;
}

SequenceGen.ms_nSequence = 0;

SequenceGen.getNextSequence = function()
{
	return ++SequenceGen.ms_nSequence;
}

/**
 *  Auxiliary services needed by MET and that are already defined in RINA
 *  Define them here as this file is only used by MET (most of the code below stems from RINA team)
 */

angular.module('sedAngularApp')
.controller("WbAngularSedCtrl", WbAngularSedCtrl);

function WbAngularSedCtrl()
{

}

/**
 *  Auxiliary services needed by MET and that are already defined in RINA
 *  Define them here as this file is only used by MET (most of the code below stems from RINA team)
 */
angular.module('sedAngularApp')
.controller("WbAngularSedChildCtrl", WbAngularSedChildCtrl);

function WbAngularSedChildCtrl()
{

}


sedAngularApp.lazy = sedAngularApp;



//angular.module('sedAngularApp')
sedAngularApp
.factory('dialogsSvc',
  ['$modal', function ($modal) {
    return {
      OKDialog: okDialog
    };

    function okDialog(message) {
      return $modal.open({
        template: '<div> \
                    <div class="modal-header"> \
                      <span style="font-size:large" translate>Information</span> \
                    </div> \
                    <div class="modal-body" > \
                      <span style="font-size:larger">{{params.message}}</span> \
                    </div> \
                    <div class="modal-footer"> \
                      <button ng-click="onOk()" type="button" class="btn btn-sm btn-primary btn-webic" wb-focus-when="true">OK</button> \
                    </div> \
                  </div>',
        controller: 'okDialogCtrl',
        backdrop: 'static',
        windowClass: 'rina-yes-no-popup',
        resolve: {
          params: function () {
            return {message: message};
          }
        }
      });
    }
  }])
.controller('okDialogCtrl',
  ['$scope', '$modalInstance', 'params', function ($scope, $modalInstance, params) {
    $scope.params = params;

    $scope.onOk = function () {
      $modalInstance.close(false);
    };

  }]);

angular.module('sedAngularApp')
//sedAngularApp
.directive('bgSplitter', function() {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: {
      orientation: '@',
      position: "="
    },
    template: '<div class="split-panes {{orientation}}" ng-transclude></div>',
    controller: function ($scope) {
      $scope.panes = [];

      this.addPane = function(pane){
        if ($scope.panes.length > 1)
          throw 'splitters can only have two panes';
        $scope.panes.push(pane);
        return $scope.panes.length;
      };
    },
    link: function(scope, element, attrs) {
      var handler = angular.element('<div class="split-handler"></div>');
      var pane1 = scope.panes[0];
      var pane2 = scope.panes[1];
      var vertical = scope.orientation == 'vertical';
      var pane1Min = pane1.minSize || 0;
      var pane1Initial = pane1.initialSize;
      var pane2Min = pane2.minSize || 0;
      var drag = false;

      pane1.elem.after(handler);

      if(pane1Initial){
        var ipos = pane1Initial;
        if(ipos.endsWith('%')) {
          var bounds = element[0].getBoundingClientRect();
          var height = bounds.bottom - bounds.top;
          ipos =  height * ipos.substring(0, ipos.length - 1)/100;
        }
        handler.css('top', ipos + 'px');
        pane1.elem.css('height', ipos + 'px');
        pane2.elem.css('top', ipos + 'px');
      }

      scope.$watch('position', function(){
        var pos = scope.position;
        if(!pos) return;

        var bounds = element[0].getBoundingClientRect();
        var h = bounds.height;
        pos = h - pos;
        handler.css('top', pos + 'px');
        pane1.elem.css('height', pos + 'px');
        pane2.elem.css('top', pos + 'px');
      });

      element.bind('mousemove', function (ev) {
        if (!drag) return;

        var bounds = element[0].getBoundingClientRect();
        var pos = 0;
        
        if (vertical) {

          var height = bounds.bottom - bounds.top;
          pos = ev.clientY - bounds.top;

          if (pos < pane1Min) return;
          if (height - pos < pane2Min) return;

          handler.css('top', pos + 'px');
          pane1.elem.css('height', pos + 'px');
          pane2.elem.css('top', pos + 'px');

          var bounds = element[0].getBoundingClientRect();
          var h = bounds.height;
          scope.position = h - pos;;
        } else {

          var width = bounds.right - bounds.left;
          pos = ev.clientX - bounds.left;

          if (pos < pane1Min) return;
          if (width - pos < pane2Min) return;

          handler.css('left', pos + 'px');
          pane1.elem.css('width', pos + 'px');
          pane2.elem.css('left', pos + 'px');
        }
      });

      handler.bind('mousedown', function (ev) {
        ev.preventDefault();
        drag = true;
      });

      angular.element(document).bind('mouseup', function (ev) {
        drag = false;
      });
    }
  };
})
.directive('bgPane', function () {
  return {
    restrict: 'E',
    require: '^bgSplitter',
    replace: true,
    transclude: true,
    scope: {
      minSize: '=',
      initialSize: '=',
      navigateTo: "=",
      onNavigate: "&",
      disableScrollbar: "="
    },
    template:
      '<div class="split-pane{{index}}"> \
        <div ng-if="disableScrollbar" ng-transclude></div> \
        <div ng-if="!disableScrollbar" style="height:100%;"> \
            <div ng-transclude></div> \
        </div> \
      </div>',
    link: function(scope, element, attrs, bgSplitterCtrl) {
      scope.elem = element;
      scope.index = bgSplitterCtrl.addPane(scope);
    }
  };
});

//Service for scrolling
sedAngularApp.service('anchorSmoothScroll', function()
{

	//this.scrollTo = function(eID, divToScroll)
	this.scrollTo = function(element, divToScroll, scope)
	{
		// the <div id = "content_[[sedNumber]]" ...> is the actual scrollable div. We need to
		// consider its top as offset for scrolling
		var elemOffsetTop = 0;
		//var helem = document.getElementById("content");
		var helem = divToScroll;
		while (helem != null)
		{
			elemOffsetTop += helem.offsetTop;
			helem = helem.offsetParent;
		}

		var startY = currentYPosition(divToScroll);
		//var stopY = elmYPosition(eID, divToScroll);
		var stopY = elmYPosition(element);

		stopY -= elemOffsetTop;
		if (stopY < 0)
			stopY = 0;
		var distance = stopY > startY ? stopY - startY : startY - stopY;
		if (distance < 100)
		{
			if (!divToScroll)
				scrollTo(0, stopY);
			else
				divToScroll.scrollTop = stopY;
			return;
		}
		var speed = Math.round(distance / 100);
		if (speed >= 20)
			speed = 20;
		var step = Math.round(distance / 25);
		var leapY = stopY > startY ? startY + step : startY - step;
		var timer = 0;
		if (stopY > startY)
		{
			for (var i = startY; i < stopY; i += step)
			{
				if (!divToScroll)
					setTimeout("window.scrollTo(0, " + leapY + ")", timer * speed);
				else
					setTimeout(function()
					{
						divToScroll.scrollTop = leapY;
					}, timer * speed);
				leapY += step;
				if (leapY > stopY)
					leapY = stopY;
				timer++;
			}
			return;
		}
		for (var i = startY; i > stopY; i -= step)
		{
			if (!divToScroll)
				setTimeout("window.scrollTo(0, " + leapY + ")", timer * speed);
			else
				setTimeout(function()
				{
					divToScroll.scrollTop = leapY;
				}, timer * speed);

			leapY -= step;
			if (leapY < stopY)
				leapY = stopY;
			timer++;
		}

		function currentYPosition(divToScroll)
		{
			if (divToScroll)
				return divToScroll.scrollTop;
			// Firefox, Chrome, Opera, Safari
			if (self.pageYOffset)
				return self.pageYOffset;
			// Internet Explorer 6 - standards mode
			if (document.documentElement && document.documentElement.scrollTop)
				return document.documentElement.scrollTop;
			// Internet Explorer 6, 7 and 8
			if (document.body.scrollTop)
				return document.body.scrollTop;
			return 0;
		}

		//function elmYPosition(eID)
		function elmYPosition(element)
		{
			//var elm = document.getElementById(eID);
			var elm = element;
			var y = elm.offsetTop;
			var node = elm;
			while (node.offsetParent && node.offsetParent != document.body)
			{
				node = node.offsetParent;
				y += node.offsetTop;
			}
			return y;
		}
	};
});

