// Copyright 2023 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import '../../../ui/legacy/legacy.js';

import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
import * as LitHtml from '../../../ui/lit-html/lit-html.js';

// clean-css does not compile this file correctly. So as a workaround adding styles inline.
const styles = `
  :host {
    --current-main-area-size: 50%;
    --resizer-size: 3px;
    --min-main-area-size: 200px;
    --min-sidebar-size: 150px;
    --main-area-size: calc(max(var(--current-main-area-size), var(--min-main-area-size)));

    height: 100%;
    width: 100%;
    display: block;
    overflow: auto;
  }

  .wrapper {
    display: flex;
    flex-direction: row;
    height: 100%;
    width: 100%;
    container: sidebar / size; /* stylelint-disable-line property-no-unknown */
  }

  .container {
    --resizer-position: calc(min(var(--main-area-size), calc(100% - var(--min-sidebar-size))));
    --min-container-size: calc(var(--min-sidebar-size) + var(--min-main-area-size) + var(--resizer-size));

    display: flex;
    flex-direction: row;
    height: 100%;
    width: 100%;
    position: relative;
    gap: var(--resizer-size);

    min-width: var(--min-container-size);
  }

  #resizer {
    background-color: var(--color-background-elevation-1);
    position: absolute;
    user-select: none;

    /* horizontal */
    width: var(--resizer-size);
    cursor: col-resize;
    left: var(--resizer-position);
    bottom: 0;
    top: 0;
  }

  slot {
    overflow: auto;
    display: block;
  }

  slot[name="main"] {

    /* horizontal */
    width: var(--resizer-position);
    min-width: var(--min-main-area-size);
  }

  slot[name="sidebar"] {
    flex: 1 0 0;

    min-width: var(--min-sidebar-size);
  }

  @container sidebar (max-width: 600px) and (min-height: 600px) { /* stylelint-disable-line at-rule-no-unknown */
    .container {
      flex-direction: column;
      min-height: var(--min-container-size);
      min-width: auto;
    }

    #resizer {
      width: auto;
      height: var(--resizer-size);
      cursor: row-resize;
      top: var(--resizer-position);
      left: 0;
      right: 0;
    }

    slot[name="main"] {
      width: auto;
      min-width: auto;
      height: var(--resizer-position);
      min-height: var(--min-main-area-size);
    }

    slot[name="sidebar"] {
      min-width: auto;
      min-height: var(--min-sidebar-size);
    }
  }
`;

declare global {
  interface HTMLElementTagNameMap {
    'devtools-split-view': SplitView;
  }
}

const splitViewStyles = new CSSStyleSheet();
splitViewStyles.replaceSync(styles);

export class SplitView extends HTMLElement {
  static readonly litTagName = LitHtml.literal`devtools-split-view`;
  readonly #shadow = this.attachShadow({mode: 'open'});
  #mousePos = [0, 0];
  #mainAxisIdx = 0;
  #mainDimensions = [0, 0];
  #observer?: ResizeObserver;

  connectedCallback(): void {
    this.style.setProperty('--current-main-area-size', '60%');
    this.#shadow.adoptedStyleSheets = [splitViewStyles];
    this.#observer = new ResizeObserver(
        entries => this.#onResize(entries[0].contentRect),
    );
    this.#observer.observe(this);
    this.#render();
  }

  #onResize = (rect: DOMRectReadOnly): void => {
    if (rect.width <= 600 && rect.height >= 600) {
      this.#mainAxisIdx = 1;
    } else {
      this.#mainAxisIdx = 0;
    }
    this.style.setProperty('--current-main-area-size', '60%');
  };

  #onMouseDown = (event: MouseEvent): void => {
    const main = this.#shadow.querySelector('slot[name=main]');
    if (!main) {
      throw new Error('Main slot not found');
    }
    const rect = main.getBoundingClientRect();
    this.#mainDimensions = [rect.width, rect.height];
    this.#mousePos = [event.clientX, event.clientY];
    window.addEventListener('mousemove', this.#onMouseMove, true);
    window.addEventListener('mouseup', this.#onMouseUp, true);
  };

  #onMouseUp = (): void => {
    window.removeEventListener('mousemove', this.#onMouseMove, true);
    window.removeEventListener('mouseup', this.#onMouseUp, true);
  };

  #onMouseMove = (event: MouseEvent): void => {
    const mousePos = [event.clientX, event.clientY];
    const delta = mousePos[this.#mainAxisIdx] - this.#mousePos[this.#mainAxisIdx];
    const rect = this.getBoundingClientRect();
    const containerDimensions = [rect.width, rect.height];
    const length = ((this.#mainDimensions[this.#mainAxisIdx] + delta) * 100) / containerDimensions[this.#mainAxisIdx];
    this.style.setProperty('--current-main-area-size', length + '%');
  };

  #render = (): void => {
    // clang-format off
    LitHtml.render(
      LitHtml.html`
        <div class="wrapper">
          <div class="container">
            <slot name="main"></slot>
            <div id="resizer" @mousedown=${this.#onMouseDown}></div>
            <slot name="sidebar"></slot>
          </div>
        </div>
      `,
      this.#shadow,
      { host: this },
    );
    // clang-format on
  };
}

ComponentHelpers.CustomElements.defineComponent(
    'devtools-split-view',
    SplitView,
);
