import { Guid } from './../../resources/elements/utilities/guid';
import { bindable, BindingEngine, bindingMode, computedFrom, customElement, Disposable, viewResources } from "aurelia-framework";
import { BaseInput } from "./base-input";
import { InputWrapper } from "./input-wrapper";

@customElement("ui-textarea")
@viewResources(InputWrapper)
export class UITextarea extends BaseInput {
  @bindable({ defaultBindingMode: bindingMode.twoWay })
  public value: string;
  @bindable({ defaultBindingMode: bindingMode.twoWay })
  public number: number = null;

  @bindable()
  public placeholder: string = "";

  @bindable()
  public maxHeight: number = 168;
  @bindable()
  public minHeight: number = 48;

  @bindable()
  public resizable: boolean = false;

  @bindable()
  public size: 'sm' | 'md' | 'lg' | 'xl' = 'sm';

  protected disposable: Disposable;
  public isValueObservable: boolean = true;
  private hiddenDivId: string;

  constructor(element: Element, protected bindingEngine: BindingEngine) {
    super(element);
    this.hiddenDivId = Guid.newGuid().toString();
  }

  @computedFrom("value", "maxlength")
  get counter() {
    if (this.maxlength) {
      return `${this.value ? this.value.length : 0} of ${this.maxlength}`;
    } else {
      return `${this.value ? this.value.length : 0}`;
    }
  }

  protected attached() {
    this.textareaAutoResize();
  }

  public valueChanged(newValue, oldValue): void {
    if (this.isValueObservable) {
      this.textareaAutoResize();
    }
  }

  protected detached() {
    this.disposable?.dispose();
    let hiddenDiv = $('#' + this.hiddenDivId).first();
    if (hiddenDiv != null) {
      hiddenDiv.detach();
    }
  }

  protected textareaAutoResize() {
    let $textarea: JQuery<HTMLTextAreaElement> = $(this.inputEl as HTMLTextAreaElement);
    if ($textarea.length == 0) {
      return;
    }

    // Textarea Auto Resize
    let hiddenDiv = $('#' + this.hiddenDivId).first();// $('.hiddendiv').first();
    if (!hiddenDiv.length) {
      hiddenDiv = $('<div id=' + this.hiddenDivId + ' class="hiddendiv common"></div>');
      $('body').append(hiddenDiv);
    }

    if (this.allowClear) {
      $textarea.css('padding-right', '22.5px');
    }

    // Set font properties of hiddenDiv
    let fontFamily = $textarea.css('font-family');
    let fontSize = $textarea.css('font-size');
    let fontWeight = $textarea.css('font-weight');
    let lineHeight = $textarea.css('line-height');
    let letterSpacing = $textarea.css('letter-spacing');

    // Firefox can't handle padding shorthand.
    let paddingTop = $textarea.css('padding-top');
    let paddingRight = $textarea.css('padding-right');
    let paddingBottom = $textarea.css('padding-bottom');
    let paddingLeft = $textarea.css('padding-left');

    if (fontFamily) {
      hiddenDiv.css('font-family', fontFamily);
    }
    if (fontSize) {
      hiddenDiv.css('font-size', fontSize);
    }
    if (fontWeight) {
      hiddenDiv.css('font-weight', fontWeight);
    }
    if (lineHeight) {
      hiddenDiv.css('line-height', lineHeight);
    }
    if (letterSpacing) {
      hiddenDiv.css('letter-spacing', letterSpacing);
    }

    if (paddingTop) {
      hiddenDiv.css('padding-top', paddingTop);
    }
    if (paddingRight) {
      hiddenDiv.css('padding-right', paddingRight);
    }
    if (paddingBottom) {
      hiddenDiv.css('padding-bottom', paddingBottom);
    }
    if (paddingLeft) {
      hiddenDiv.css('padding-left', paddingLeft);
    }

    // Set original-height, if none
    if (!$textarea.data('original-height')) {
      $textarea.data('original-height', $textarea.height());
    }

    if ($textarea.attr('wrap') === 'off') {
      hiddenDiv.css('overflow-wrap', 'normal').css('white-space', 'pre');
    }

    hiddenDiv.text($textarea[0].value + '\n');
    let content = hiddenDiv.html().replace(/\n/g, '<br>');
    hiddenDiv.html(content);

    // When textarea is hidden, width goes crazy.
    // Approximate with half of window size
    if ($textarea[0].offsetWidth > 0 && $textarea[0].offsetHeight > 0) {
      hiddenDiv.css('width', $textarea.width() + 'px');
    }
    else {
      hiddenDiv.css('width', window.innerWidth / 2 + 'px');
    }

    /**
     * Resize if the new height is greater than the
     * original height of the textarea
     */
    let height: number = this.minHeight;
    if ($textarea.data('original-height') <= hiddenDiv.innerHeight()) {
      height = hiddenDiv.innerHeight();
    }
    else if ($textarea[0].value.length < $textarea.data('previous-length')) {
      /**
       * In case the new height is less than original height, it
       * means the textarea has less text than before
       * So we set the height to the original one
       */
      height = $textarea.data('original-height');
    }

    if (this.minHeight != null && this.minHeight > 0) {
      if (height < this.minHeight) {
        height = this.minHeight;
      }
    }

    if (this.maxHeight != null && this.maxHeight > 0) {
      if (this.allowClear) {
        let clearBtn: JQuery<HTMLElement> = $(this.element).find('div.ui-input__clear').first();
        //TODO Find a way to check if this is an instanceof UIMLTextarea because clear buttton is not located on the same element
        // if(this instanceof UIMLTextarea) {
        //   clearBtn = $($textarea.parent).find('div.ui-input__clear').first();
        // }
        // else {
        //   clearBtn = $($textarea).find('div.ui-input__clear').first();
        // }
        clearBtn.css('right', (height > this.maxHeight ? '18px' : '0'));
      }

      if (height > this.maxHeight) {
        height = this.maxHeight;
      }
    }

    $textarea.css('height', height + 'px');
    $textarea.data('previous-length', $textarea[0].value.length);
  }
}
