/*global imce:true*/
(function ($, Drupal, imce) {
  'use strict';

  /**
   * @file
   * Defines imce Item object.
   */

  /**
   * Imce Item.
   */
  imce.Item = function (name) {
    this.construct(name);
  };

  /**
   * Item prototype.
   */
  var Item = imce.Item.prototype;

  /**
   * Constructs Imce Item.
   */
  Item.construct = function (name) {
    this.createEl();
    this.setName(name);
  };

  /**
   * Creates Item elements.
   */
  Item.createEl = function () {
    var el;
    var children;
    var Item = this;
    if (!Item.el) {
      el = Item.el = imce.createEl('<div class="imce-item"><div class="imce-item-date"></div><div class="imce-item-height"></div><div class="imce-item-width"></div><div class="imce-item-size"></div><div class="imce-item-icon imce-ficon"></div><div class="imce-item-name"></div></div>');
      el.onmousedown = imce.eItemMousedown;
      el.ondblclick = imce.eItemDblclick;
      el.Item = Item;
      children = el.children;
      Item.dateEl = children[0];
      Item.heightEl = children[1];
      Item.widthEl = children[2];
      Item.sizeEl = children[3];
      Item.iconEl = children[4];
      Item.nameEl = children[5];
    }
  };

  /**
   * Appends the item to a parent.
   */
  Item.appendTo = function (parent) {
    parent.appendItem(this);
  };

  /**
   * Removes the item.
   */
  Item.remove = function (shallow) {
    if (this.parent) {
      this.parent.removeItem(this, shallow);
    }
  };

  /**
   * Item click handler.
   */
  Item.click = function (e) {
    var Item = this;
    if (e) {
      // Range select
      if (e.shiftKey) {
        var Folder = imce.activeFolder;
        var lastItem = imce.getLastSelected();
        var start = lastItem ? Folder.indexOf(lastItem) : -1;
        var end = Folder.indexOf(Item);
        var step = start < end ? 1 : -1;
        while (start !== end) {
          Folder.getItemAt(start += step).select();
        }
        return;
      }
      // Toggle select
      if (e.ctrlKey) {
        return Item.toggleSelect();
      }
    }
    var i;
    var selection = imce.getSelection();
    for (i in selection) {
      if (imce.owns(selection, i) && selection[i] !== Item) {
        selection[i].deselect();
      }
    }
    Item.select();
  };

  /**
   * Double click handler.
   */
  Item.dblClick = function () {
    if (imce.sendtoHandler) {
      imce.runSendtoHandler([this]);
    }
    else {
      this.open();
    }
  };

  /**
   * Opens item.
   */
  Item.open = function () {
    var url = this.getUrl();
    if (url) {
      window.open(url);
    }
  };

  /**
   * Selects item.
   */
  Item.select = function () {
    imce.selectItem(this);
  };

  /**
   * Deselects item.
   */
  Item.deselect = function () {
    imce.deselectItem(this);
  };

  /**
   * Toggles select.
   */
  Item.toggleSelect = function () {
    if (this.selected) {
      this.deselect();
    }
    else {
      this.select();
    }
  };

  /**
   * Sets/unsets the item busy.
   */
  Item.setBusy = function (state) {
    this.toggleState('busy', !!state);
  };

  /**
   * Sets/unsets the item disabled.
   */
  Item.setDisabled = function (state) {
    this.toggleState('disabled', !!state);
  };

  /**
   * Checks if the item is ready for an operation.
   */
  Item.isReady = function () {
    return !this.disabled && !this.busy;
  };

  /**
   * Returns item path relative to the root.
   */
  Item.getPath = function () {
    var parent;
    var path = this.path;
    if (path) {
      return path;
    }
    if (parent = this.parent) {
      if (path = parent.getPath()) {
        return imce.joinPaths(path, this.name);
      }
    }
  };

  /**
   * Sets the item path.
   */
  Item.setPath = function (path) {
    this.path = path;
  };

  /**
   * Returns item uri.
   */
  Item.getUri = function () {
    var path = this.getPath();
    if (path) {
      return imce.joinPaths(imce.getConf('root_uri', '/'), path);
    }
  };

  /**
   * Returns item url.
   * Uncached parameter allows unique urls per size+date which is useful to display resized/cropped images
   */
  Item.getUrl = function (absolute, uncached) {
    // Allow urls set by plugins on server side.
    var url = this.url;
    if (!url) {
      var rootUrl = imce.getConf('root_url');
      if (rootUrl) {
        var path = encodeURIComponent(this.getPath()).replace(/%2F/g, '/');
        url = imce.joinPaths(rootUrl, path);
      }
    }
    if (url) {
      if (absolute && url.charAt(0) === '/' && url.charAt(1) !== '/') {
        url = location.protocol + '//' + location.host + url;
      }
      if (uncached) {
        url += (url.indexOf('?') === -1 ? '?' : '&') + ('s' + this.size) + ('d' + this.date);
      }
    }
    return url || '';
  };

  /**
   * Formats item uri.
   */
  Item.formatUri = function () {
    return Drupal.checkPlain(this.getUri());
  };

  /**
   * Formats item path.
   */
  Item.formatPath = function () {
    return Drupal.checkPlain(this.path === '.' ? this.name : this.getPath());
  };

  /**
   * Formats item name.
   */
  Item.formatName = function () {
    return Drupal.checkPlain(this.name);
  };

  /**
   * Formats item size.
   */
  Item.formatSize = function () {
    return imce.formatSize(this.size);
  };

  /**
   * Formats item date.
   */
  Item.formatDate = function (dayOnly) {
    return imce.formatDate(this.date, dayOnly);
  };

  /**
   * Formats item width.
   */
  Item.formatWidth = function () {
    return this.width ? this.width * 1 + '' : '';
  };

  /**
   * Formats item height.
   */
  Item.formatHeight = function () {
    return this.height ? this.height * 1 + '' : '';
  };

  /**
   * Formats item dimensions.
   */
  Item.formatDimensions = function () {
    return this.width ? this.width * 1 + 'x' + this.height * 1 : '';
  };

  /**
   * Adds new item properties.
   * Fires property change events for changed properties.
   */
  Item.extend = function (props) {
    if (props) {
      for (var i in props) {
        if (!imce.owns(props, i)) {
          continue;
        }
        this.setProperty(i, props[i]);
      }
    }
  };

  /**
   * Sets property value and trigger change events.
   */
  Item.setProperty = function (prop, val) {
    var oldval = this[prop];
    if (oldval !== val) {
      this[prop] = val;
      this.triggerPropertyChange(prop, oldval);
    }
  };

  /**
   * Sets item name.
   */
  Item.setName = function (name) {
    this.setProperty('name', name);
  };

  /**
   * Triggers property change handlers.
   */
  Item.triggerPropertyChange = function (prop, oldval) {
    var method = 'on' + prop.charAt(0).toUpperCase() + prop.substring(1) + 'Change';
    if (this[method]) {
      this[method](oldval);
      if (this === imce.previewingItem) {
        imce.updatePreview();
      }
    }
  };

  /**
   * Name change handler.
   */
  Item.onNameChange = function (oldname) {
    var Item = this;
    var name = Item.formatName();
    Item.nameEl.innerHTML = name;
    Item.nameEl.title = name;
    if (Item.parent) {
      Item.parent.onItemNameChange(Item, oldname);
    }
  };

  /**
   * Thumbnail change handler.
   */
  Item.onThumbnailChange = function (oldval) {
    if (this.thumbnail) {
      this.iconEl.innerHTML = '<img src="' + this.thumbnail + '" alt="thumbnail">';
      this.iconEl.className += ' imce-item-thumbnail';
    }
    else {
      this.iconEl.innerHTML = '';
      $(this.iconEl).removeClass('imce-item-thumbnail');
    }
  };

  /**
   * Size change handler.
   */
  Item.onSizeChange = function (oldval) {
    var size = this.formatSize();
    this.sizeEl.innerHTML = size;
    this.sizeEl.title = size;
  };

  /**
   * Date change handler.
   */
  Item.onDateChange = function (oldval) {
    var date = this.formatDate(true);
    this.dateEl.innerHTML = date;
    this.dateEl.title = date;
  };

  /**
   * Width change handler.
   */
  Item.onWidthChange = function (oldval) {
    var width = this.formatWidth();
    this.widthEl.innerHTML = width;
    this.widthEl.title = width;
  };

  /**
   * Height change handler.
   */
  Item.onHeightChange = function (oldval) {
    var height = this.formatHeight();
    this.heightEl.innerHTML = height;
    this.heightEl.title = height;
  };


  /**
   * Creates preview element.
   */
  Item.createPreviewEl = function () {
    var el;
    var Item = this;
    var prvEl = imce.createEl('<div class="imce-item-preview"></div>');
    // Info
    var infoEl = imce.createEl('<div class="imce-preview-info"></div>');
    prvEl.appendChild(infoEl);
    // Folder
    if (Item.isFolder) {
      infoEl.appendChild(imce.createEl('<div class="path">' + Item.formatUri() + '</div>'));
      prvEl.className += ' folder';
    }
    // File
    else {
      var url = Item.getUrl(true);
      infoEl.appendChild(imce.createEl('<div class="url"><a href="' + url + '" target="_blank">' + url + '</a></div>'));
    }
    // Size
    if (Item.size) {
      infoEl.appendChild(imce.createEl('<div class="size">' + Item.formatSize() + '</div>'));
    }
    // Dimensions
    if (Item.width) {
      infoEl.appendChild(imce.createEl('<div class="dimensions">' + Item.formatDimensions() + '</div>'));
    }
    // Date
    if (Item.date) {
      infoEl.appendChild(imce.createEl('<div class="date">' + Item.formatDate() + '</div>'));
    }
    // Image
    if (Item.isImageSource() && imce.getConf('preview_images', 1)) {
      el = imce.createEl('<div class="imce-preview-image"><img src="' + Item.getUrl(false, true) + '"></div>');
      prvEl.appendChild(el);
      prvEl.className += ' image';
      el.firstChild.onclick = imce.ePrvImgClick;
      el.firstChild.onload = (e) => Item.prvImgLoad(e);
    }
    return prvEl;
  };

  /**
   * Load event for the preview image.
   */
  Item.prvImgLoad = function (e) {
    if (!this.width) {
      const { width, height } = e.target;
      this.extend({ width, height });
    }
  };

  /**
   * Sets a state by name.
   */
  Item.setState = function (name) {
    var el;
    var Item = this;
    if (!Item[name]) {
      Item[name] = true;
      $(Item.el).addClass(name);
      if (el = Item.branchEl) {
        $(el).addClass(name);
      }
    }
  };

  /**
   * Unsets a state by name.
   */
  Item.unsetState = function (name) {
    var el;
    var Item = this;
    if (Item[name]) {
      Item[name] = false;
      $(Item.el).removeClass(name);
      if (el = Item.branchEl) {
        $(el).removeClass(name);
      }
    }
  };

  /**
   * Toggles a state by name.
   */
  Item.toggleState = function (name, state) {
    if (state == null) {
      state = !this[name];
    }
    this[state ? 'setState' : 'unsetState'](name);
  };

  /**
   * Scroll the item element into view.
   */
  Item.scrollIntoView = function () {
    imce.scrollToEl(this.el, imce.contentEl, imce.contentHeaderEl.offsetHeight, imce.contentStatusEl.offsetHeight);
  };

  /**
   * Check if the item can be used as an image source.
   */
  Item.isImageSource = function () {
    return false;
  };

  /**
   * Check if the item name has image extension.
   */
  Item.hasImageExtension = function () {
    return false;
  };

  /**
   * Mousedown event for items.
   */
  imce.eItemMousedown = function (event) {
    var e = imce.eFix(event);
    this.Item.click(e);
    return !(e.ctrlKey || e.shiftKey);
  };

  /**
   * Double-click event for items.
   */
  imce.eItemDblclick = function (event) {
    this.Item.dblClick();
    return false;
  };

  /**
   * Click event for preview image.
   */
  imce.ePrvImgClick = function () {
    var Item = imce.previewingItem;
    if (Item) {
      Item.dblClick();
    }
    return false;
  };

})(jQuery, Drupal, imce);
