/**
 * A block with an optional icon and up to two lines of text.
 */
beestat.component.tile = function() {
  beestat.component.apply(this, arguments);
};
beestat.extend(beestat.component.tile, beestat.component);

/**
 * Decorate
 *
 * @param {rocket.Elements} parent
 */
beestat.component.tile.prototype.decorate_ = function(parent) {
  const self = this;

  let size_constant;
  switch (this.get_size_()) {
  case 'large':
    size_constant = 48;
    break;
  case 'small':
    size_constant = 24;
    break;
  case 'medium':
  default:
    size_constant = 32;
  }

  const background_color = this.background_color_ || 'none';
  const text_color = this.text_color_ || '#fff';
  const tabbable = this.tabbable_ || false;
  const shadow = this.shadow_ === undefined ? true : this.shadow_;
  const display = this.display_ === 'block' ? 'flex' : 'inline-flex';
  let border_radius;
  if (this.type_ === 'pill') {
    border_radius = size_constant;
  } else {
    border_radius = beestat.style.size.border_radius;
  }

  this.container_ = document.createElement('div');

  Object.assign(this.container_.style, {
    'background': background_color,
    'border-radius': `${border_radius}px`,
    'height': `${size_constant}px`,
    'display': display,
    'align-items': 'center',
    'color': text_color,
    'user-select': 'none',
    'transition': 'color 200ms ease, background 200ms ease',
    'outline-offset': '1px',
    'text-align': 'left'
  });

  if (shadow === true) {
    Object.assign(this.container_.style, {
      'box-shadow': '0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)'
    });
  }

  parent.appendChild(this.container_);

  // Padding. Basically for icon only make it a nice square button.
  if (this.get_text_() === undefined) {
    Object.assign(this.container_.style, {
      'width': `${size_constant}px`,
      'justify-content': 'center'
    });
  } else {
    Object.assign(this.container_.style, {
      'padding-left': `${(beestat.style.size.gutter / 2)}px`,
      'padding-right': `${(beestat.style.size.gutter / 2)}px`,
    });
  }

  // Width override
  if (this.width_ !== undefined) {
    Object.assign(this.container_.style, {
      'width': `${this.width_}px`
    });
  }

  // Tabbable
  if (tabbable === true) {
    this.container_.setAttribute('tabIndex', '0');
  }

  // Title
  if (this.title_ !== undefined) {
    this.container_.setAttribute('title', this.title_);
  }

  // Hover
  if (
    this.text_hover_color_ !== undefined ||
    this.background_hover_color_ !== undefined
  ) {
    this.container_.style.cursor = 'pointer';

    const mouseenter_style = {};
    if (this.text_hover_color_ !== undefined) {
      mouseenter_style.color = this.text_hover_color_;
    }
    if (this.background_hover_color_ !== undefined) {
      mouseenter_style.background = this.background_hover_color_;
    }

    const mouseleave_style = {};
    mouseleave_style.color =
      (this.text_color_ !== undefined) ? this.text_color_ : '';
    mouseleave_style.background =
      (this.background_color_ !== undefined) ? this.background_color_ : '';

    this.container_.addEventListener('mouseenter', function() {
      Object.assign(self.container_.style, mouseenter_style);
    });
    this.container_.addEventListener('mouseleave', function() {
      Object.assign(self.container_.style, mouseleave_style);
    });
  }

  // Focus
  if (tabbable === true) {
    this.container_.addEventListener('focus', function() {
      self.container_.style.outline = '2px solid #fff';
    });
    this.container_.addEventListener('blur', function() {
      self.container_.style.outline = 'none';
    });
    this.container_.addEventListener('keydown', function(e) {
      if (
        e.key === 'Enter' ||
        e.key === ' '
      ) {
        self.dispatchEvent(new window.Event('click'));
      }
    });
  }

  // Left and right container
  const left_container = document.createElement('div');
  this.decorate_left_(left_container);
  this.container_.appendChild(left_container);

  const right_container = document.createElement('div');
  right_container.style.minWidth = '0';
  this.decorate_right_(right_container);
  this.container_.appendChild(right_container);

  // Events
  this.container_.addEventListener('click', function() {
    self.dispatchEvent('click');
  });

  this.container_.addEventListener('mousedown', function() {
    self.dispatchEvent('mousedown');
  });
};

beestat.component.tile.prototype.decorate_left_ = function(parent) {
  if (this.get_icon_() !== undefined) {
    const icon_container = document.createElement('div');
    if (this.get_text_() !== undefined) {
      icon_container.style.marginRight = (beestat.style.size.gutter / 2) + 'px';
    }
    parent.appendChild(icon_container);

    new beestat.component.icon(this.get_icon_())
      .set_bubble_text(this.bubble_text_)
      .set_bubble_color(this.bubble_color_)
      .set_size(this.get_size_() === 'large' ? 32 : 24)
      .render($(icon_container));
  }
};

/**
 * Decorate the right side of the tile.
 *
 * @param {HTMLElement} parent
 */
beestat.component.tile.prototype.decorate_right_ = function(parent) {
  if (Array.isArray(this.get_text_()) === true) {
    const line_1_container = document.createElement('div');
    line_1_container.innerText = this.get_text_()[0];
    line_1_container.style.fontWeight = beestat.style.font_weight.bold;
    line_1_container.style.whiteSpace = 'nowrap';
    line_1_container.style.overflow = 'hidden';
    line_1_container.style.textOverflow = 'ellipsis';
    parent.appendChild(line_1_container);

    const line_2_container = document.createElement('div');
    line_2_container.innerText = this.get_text_()[1];
    line_2_container.style.fontWeight = beestat.style.font_weight.light;
    line_2_container.style.whiteSpace = 'nowrap';
    line_2_container.style.overflow = 'hidden';
    line_2_container.style.textOverflow = 'ellipsis';
    parent.appendChild(line_2_container);
  } else if (this.get_text_() !== undefined) {
    const text_container = document.createElement('div');
    text_container.innerText = this.get_text_();
    text_container.style.fontWeight = beestat.style.font_weight.normal;
    text_container.style.whiteSpace = 'nowrap';
    text_container.style.overflow = 'hidden';
    text_container.style.textOverflow = 'ellipsis';
    parent.appendChild(text_container);
  }
};

/**
 * Set the icon.
 *
 * @param {string} icon
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_icon = function(icon) {
  this.icon_ = icon;

  if (this.rendered_ === true) {
    this.rerender();
  }

  return this;
};

/**
 * Set the size. Default is medium.
 *
 * @param {string} size large|medium|small
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_size = function(size) {
  this.size_ = size;

  if (this.rendered_ === true) {
    this.rerender();
  }

  return this;
};

/**
 * Get the size of this tile.
 *
 * @return {string} The size of this tile.
 */
beestat.component.tile.prototype.get_size_ = function() {
  return this.size_;
};

/**
 * Get the icon for this tile.
 *
 * @return {string} The icon.
 */
beestat.component.tile.prototype.get_icon_ = function() {
  return this.icon_;
};

/**
 * Set the text of the button.
 *
 * @param {string|array} text A single string or array of strings. If an array
 * is passed multiple lines of text will be shown.
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_text = function(text) {
  this.text_ = text;

  if (this.rendered_ === true) {
    this.rerender();
  }

  return this;
};

/**
 * Get the text for this tile.
 *
 * @return {string} The text for this tile.
 */
beestat.component.tile.prototype.get_text_ = function() {
  return this.text_;
};

/**
 * Set the background color.
 *
 * @param {string} background_color
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_background_color = function(background_color) {
  this.background_color_ = background_color;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Set whether or not there is a shadow. Default true.
 *
 * @param {boolean} shadow
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_shadow = function(shadow) {
  this.shadow_ = shadow;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Set the text color.
 *
 * @param {string} text_color
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_text_color = function(text_color) {
  this.text_color_ = text_color;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Set the background hover color.
 *
 * @param {string} background_hover_color
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_background_hover_color = function(background_hover_color) {
  this.background_hover_color_ = background_hover_color;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Set the text hover color.
 *
 * @param {string} text_hover_color
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_text_hover_color = function(text_hover_color) {
  this.text_hover_color_ = text_hover_color;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Set the title for the tile.
 *
 * @param {string} title
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_title = function(title) {
  this.title_ = title;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Get the container for this tile.
 *
 * @return {array} The container for this tile.
 */
beestat.component.tile.prototype.get_container = function() {
  return this.container_;
};

/**
 * Set whether or not this is tabbable. Default false.
 *
 * @param {boolean} tabbable
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_tabbable = function(tabbable) {
  this.tabbable_ = tabbable;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Set display mode.
 *
 * @param {string} display inline|block; default inline.
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_display = function(display) {
  this.display_ = display;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Set the type.
 *
 * @param {string} type Valid value is "pill" for now.
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_type = function(type) {
  this.type_ = type;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Do the normal event listener stuff. Only exists for chaining purposes.
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.addEventListener = function() {
  rocket.EventTarget.prototype.addEventListener.apply(this, arguments);
  return this;
};

/**
 * Set the text of the bubble.
 *
 * @param {string} bubble_text
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_bubble_text = function(bubble_text) {
  this.bubble_text_ = bubble_text;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Set the color of the bubble.
 *
 * @param {string} bubble_color
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_bubble_color = function(bubble_color) {
  this.bubble_color_ = bubble_color;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};

/**
 * Set the width of the button.
 *
 * @param {number} width
 *
 * @return {beestat.component.tile} This.
 */
beestat.component.tile.prototype.set_width = function(width) {
  this.width_ = width;
  if (this.rendered_ === true) {
    this.rerender();
  }
  return this;
};
