import * as colors from './00colors.js';
import * as plugins from './00plugins.js';

import { DeesContextmenu } from './dees-contextmenu.js';

import {
  customElement,
  DeesElement,
  type TemplateResult,
  property,
  html,
  css,
  unsafeCSS,
  cssManager,
  type CSSResult,
  domtools,
} from '@design.estate/dees-element';

declare global {
  interface HTMLElementTagNameMap {
    'dees-input-fileupload': DeesInputFileupload;
  }
}

@customElement('dees-input-fileupload')
export class DeesInputFileupload extends DeesElement {
  public static demo = () =>
    html`<dees-input-fileupload .label=${'Attachments'}></dees-input-fileupload>`;

  // INSTANCE
  public changeSubject = new domtools.plugins.smartrx.rxjs.Subject();

  @property({
    type: String,
  })
  public label: string = null;

  @property({
    type: String,
    reflect: true,
  })
  public key: string;

  @property({
    attribute: false,
  })
  public value: File[] = [];

  @property()
  public state: 'idle' | 'dragOver' | 'dropped' | 'uploading' | 'completed' = 'idle';

  @property({
    type: Boolean,
  })
  public required: boolean = false;

  @property({
    type: Boolean,
  })
  public disabled: boolean = false;

  @property({
    type: String,
  })
  public buttonText: string = 'Upload File...';

  constructor() {
    super();
  }

  public static styles = [
    cssManager.defaultStyles,
    css`
      :host {
        position: relative;
        display: grid;
        margin: 10px 0px;
        margin-bottom: 24px;
        color: ${cssManager.bdTheme('#333', '#ccc')};
      }

      .hidden {
        display: none;
      }

      .maincontainer {
        position: relative;
        border-radius: 3px;
        padding: 8px;
        background: ${cssManager.bdTheme('#fafafa', '#222222')};
        color: ${cssManager.bdTheme('#333', '#ccc')};
        border-top: 1px solid #ffffff10;
      }

      .maincontainer::after {
        top: 2px;
        right: 2px;
        left: 2px;
        bottom: 2px;
        transform: scale3d(0.98, 0.9, 1);
        position: absolute;
        content: '';
        display: block;
        border: 2px dashed rgba(255, 255, 255, 0);
        transition: all 0.2s;
        pointer-events: none;
        background: #00000000;
      }
      .maincontainer.dragOver::after {
        transform: scale3d(1, 1, 1);
        border: 2px dashed rgba(255, 255, 255, 0.3);
        background: #00000080;
      }

      .label {
        font-size: 14px;
        margin-bottom: 8px;
      }

      .uploadButton {
        position: relative;
        padding: 8px;
        max-width: 600px;
        background: ${cssManager.bdTheme('#fafafa', '#333333')};
        border-radius: 3px;
        text-align: center;
        font-size: 14px;
        cursor: default;
      }

      .uploadButton:hover {
        color: #fff;
        background: ${unsafeCSS(colors.dark.blue)};
      }

      .uploadCandidate {
        display: grid;
        grid-template-columns: 48px auto;
        background: #333;
        padding: 8px 8px 8px 0px;
        margin-bottom: 8px;
        text-align: left;
        border-radius: 3px;
        color: ${cssManager.bdTheme('#666', '#ccc')};
        font-family: 'Geist Sans', sans-serif;
        cursor: default;
        transition: all 0.2s;
        border-top: 1px solid #ffffff10;
      }

      .uploadCandidate:last-child {
        margin-bottom: 8px;
      }

      .uploadCandidate .icon {
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 16px;
      }

      .uploadCandidate:hover {
        background: #393939;
      }

      .uploadCandidate .description {
        font-size: 14px;
        border-left: 1px solid #ffffff10;
        padding-left: 8px;
      }
    `,
  ];

  public render(): TemplateResult {
    return html`
      <div class="hidden">
        <input type="file"></div>
      </div>
      ${this.label ? html`<div class="label">${this.label}</div>` : null}
      <div class="maincontainer ${this.state === 'dragOver' ? 'dragOver' : ''}">
        ${this.value.map(
          (fileArg) => html`
          <div class="uploadCandidate" @contextmenu=${eventArg => {
            DeesContextmenu.openContextMenuWithOptions(eventArg, [{
              iconName: 'trash',
              name: 'Remove',
              action: async () => {
                this.value.splice(this.value.indexOf(fileArg), 1);
                this.requestUpdate();
              }
            }]);
          }}>
            <div class="icon">
              <dees-icon .iconFA=${'paperclip'}></dees-icon>
            </div>
            <div class="description">
              <span style="font-weight: 600">${fileArg.name}</span><br />
              <span style="font-weight: 400">${fileArg.size}</span>
            </div>
          </div> `
        )}
        <div class="uploadButton" @click=${
          this.openFileSelector
        }>
          ${this.buttonText}
        </div>
      </div>
    `;
  }

  public async openFileSelector() {
    const inputFile: HTMLInputElement = this.shadowRoot.querySelector('input[type="file"]');
    inputFile.click();
    this.state = 'idle';
    this.buttonText = 'Upload more files...';
  }

  public async updateValue(eventArg: Event) {
    const target: any = eventArg.target;
    this.value = target.value;
    this.changeSubject.next(this);
  }

  public firstUpdated() {
    const inputFile: HTMLInputElement = this.shadowRoot.querySelector('input[type="file"]');
    inputFile.addEventListener('change', (event: Event) => {
      const target = event.target as HTMLInputElement;
      for (const file of Array.from(target.files)) {
        this.value.push(file);
      }
      this.requestUpdate();
      console.log(`Got ${this.value.length} files!`);
      // Reset the input value to allow selecting the same file again if needed
      target.value = '';
    });

    // lets handle drag and drop
    const dropArea = this.shadowRoot.querySelector('.maincontainer');
    const handlerFunction = (eventArg: DragEvent) => {
      eventArg.preventDefault();
      switch (eventArg.type) {
        case 'dragover':
          this.state = 'dragOver';
          this.buttonText = 'release to upload file...';
          break;
        case 'dragleave':
          this.state = 'idle';
          this.buttonText = 'Upload File...';
          break;
        case 'drop':
          this.state = 'idle';
          this.buttonText = 'Upload more files...';
      }
      console.log(eventArg);
      for (const file of Array.from(eventArg.dataTransfer.files)) {
        this.value.push(file);
        this.requestUpdate();
      }
      console.log(`Got ${this.value.length} files!`);
    };
    dropArea.addEventListener('dragenter', handlerFunction, false);
    dropArea.addEventListener('dragleave', handlerFunction, false);
    dropArea.addEventListener('dragover', handlerFunction, false);
    dropArea.addEventListener('drop', handlerFunction, false);
  }
}