"use strict";

var ObjectWithListeners = require('../ObjectWithListeners');
var Plugin = require('./Plugin');
var GuiUtils = require('../gui/leftPanel/GuiUtils');
var GuiConnector = require('../GuiConnector');
var InvalidArgumentError = require('../InvalidArgumentError');
var isUrl = require('is-url');

var Promise = require("bluebird");

// noinspection JSUnusedLocalSymbols
var logger = require('../logger');


function PluginManager(options) {
  ObjectWithListeners.call(this);
  var self = this;
  self.setProject(options.project);
  self.setMap(options.map);
  self.setElement(options.element);
  self.setConfiguration(options.configuration);
  self._plugins = [];
  self._pluginOnResizeHandlers = {};

  self.registerListenerType("onResize");
  self.addListener("onResize", function () {
    var promises = [];
    for (var i = 0; i < self._plugins.length; i++) {
      promises.push(self._plugins[i].callListeners("onResize"));
    }
    return Promise.resolve(promises);
  });
}

PluginManager.prototype = Object.create(ObjectWithListeners.prototype);
PluginManager.prototype.constructor = ObjectWithListeners;

PluginManager.prototype.setProject = function (project) {
  this._project = project;
};
PluginManager.prototype.setMap = function (map) {
  this._map = map;
};
PluginManager.prototype.getMap = function () {
  return this._map;
};
PluginManager.prototype.setElement = function (element) {
  this._element = element;
};
PluginManager.prototype.getElement = function () {
  return this._element;
};

PluginManager.prototype.setConfiguration = function (configuration) {
  this._configuration = configuration;
};

PluginManager.prototype.getConfiguration = function () {
  return this._configuration;
};

PluginManager.prototype.getPlugins = function () {
  return this._plugins;
};

PluginManager.prototype.addPlugin = function (options) {
  var self = this;
  var tabData = self.createTabForPlugin();
  var plugin;
  if (options instanceof Plugin) {
    plugin = options;
    plugin.setOptions({
      element: tabData.content,
      configuration: self.getConfiguration(),
      map: self.getMap()
    });
  } else {
    if (!self.isValidUrl(options.url)) {
      return Promise.reject(new InvalidArgumentError("url: '" + options.url + "' is invalid"));
    }
    plugin = new Plugin({
      url: options.url,
      element: tabData.content,
      configuration: self.getConfiguration(),
      map: self.getMap()
    });
    plugin.addListener("onUnload", function () {
      tabData.content.parentNode.removeChild(tabData.content);
      tabData.title.parentNode.parentNode.removeChild(tabData.title.parentNode);
    });
  }
  self._plugins.push(plugin);
  return plugin.load().then(function () {
    tabData.title.innerHTML = plugin.getName();
    var tab = $(tabData.content);
    tab.css('overflow', 'auto');
    var adjustHeight = function () {
      tab.css('height', 'calc( 100vh - ' + $(tabData.content.parentNode).offset().top + 'px )');
    };

    self._pluginOnResizeHandlers[plugin.getPluginId()] = adjustHeight;
    GuiConnector.addWindowResizeEvent(adjustHeight);
    adjustHeight();
    return self.adjustMinWidth();
  }).then(function () {
    if (self._plugins.length === 1) {
      return self.getMap().getMapCanvas().triggerListeners("resize");
    }
  }).then(function () {
    return plugin;
  });
};

PluginManager.prototype.isValidUrl = function (url) {
  return isUrl(url);
};
PluginManager.prototype.createTabForPlugin = function () {
  var self = this;
  var tabData = self._tabData;
  var guiUtils = new GuiUtils(self.getConfiguration());
  if (tabData === undefined) {
    self.getElement().style.width = "300px";
    self.getElement().style.maxWidth = "600px";
    self.getElement().style.minWidth = "150px";
    self.getElement().style.height = "100%";
    self.getElement().style.position = "relative";
    self._tabData = guiUtils.createTabDiv({element: self.getElement(), id: "plugin_tab"});
    tabData = self._tabData;
    $(tabData.element).css('position', 'absolute');
    $(tabData.element).css('top', '0');
    $(tabData.element).css('width', '100%');
  }
  return guiUtils.createTab({
    title: "",
    content: "",
    tabData: tabData
  });
};
PluginManager.prototype.adjustMinWidth = function () {
  var self = this;
  var oldVal = self.getElement().style.minWidth;
  var minWidth = 150;
  var i;
  for (i = 0; i < self._plugins.length; i++) {
    var plugin = self._plugins[i];
    var value = plugin.getMinWidth();
    if (value > minWidth) {
      minWidth = value;
    }
  }
  var newVal = minWidth + "px";
  self.getElement().style.minWidth = newVal;
  if (newVal !== oldVal) {
    return self.callListeners("onResize");
  } else {
    return Promise.resolve();
  }
};

PluginManager.prototype.removePlugin = function (plugin) {
  var self = this;
  var found = false;
  for (var i = 0; i < self._plugins.length; i++) {
    if (plugin === self._plugins[i]) {
      self._plugins.splice(i, 1);
      found = true;
    }
  }
  if (!found) {
    return Promise.reject(new Error("Plugin not registered"));
  }
  GuiConnector.removeWindowResizeEvent(self._pluginOnResizeHandlers[plugin.getPluginId()]);
  return plugin.unload().then(function () {
    return self.adjustMinWidth();
  });
};

PluginManager.prototype.destroy = function () {
  var self = this;
  var promises = [];
  var plugins = self._plugins;
  for (var i = plugins.length - 1; i >= 0; i--) {
    promises.push(self.removePlugin(plugins[i]));
  }
  return Promise.all(promises);
};


module.exports = PluginManager;