// Copyright (C) 2024 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import m from 'mithril';

import {Trash} from '../base/disposable';
import {raf} from '../core/raf_scheduler';
import {Button} from '../widgets/button';
import {MenuItem, PopupMenu2} from '../widgets/menu';

import {DEFAULT_DETAILS_CONTENT_HEIGHT} from './css_constants';
import {DragGestureHandler} from './drag_gesture_handler';

const DRAG_HANDLE_HEIGHT_PX = 28;
const UP_ICON = 'keyboard_arrow_up';
const DOWN_ICON = 'keyboard_arrow_down';

export interface Tab {
  // Unique key for this tab, passed to callbacks.
  key: string;

  // Tab title to show on the tab handle.
  title: string;

  // Whether to show a close button on the tab handle or not.
  // Default = false.
  hasCloseButton?: boolean;
}

export interface TabDropdownEntry {
  // Unique key for this tab dropdown entry.
  key: string;

  // Title to show on this entry.
  title: string;

  // Called when tab dropdown entry is clicked.
  onClick: () => void;
}

export interface DragHandleAttrs {
  // The current height of the panel.
  height: number;

  // Called when the panel is dragged.
  resize: (height: number) => void;

  // A list of tabs to show in the tab bar.
  tabs: Tab[];

  // The key of the "current" tab.
  currentTabKey?: string;

  // A list of entries to show in the tab dropdown.
  // If undefined, the tab dropdown button will not be displayed.
  tabDropdownEntries?: TabDropdownEntry[];

  // Called when a tab is clicked.
  onTabClick: (key: string) => void;

  // Called when a tab is closed using its close button.
  onTabClose?: (key: string) => void;
}

export function getDetailsHeight() {
  // This needs to be a function instead of a const to ensure the CSS constants
  // have been initialized by the time we perform this calculation;
  return DEFAULT_DETAILS_CONTENT_HEIGHT + DRAG_HANDLE_HEIGHT_PX;
}

function getFullScreenHeight() {
  const panelContainer =
      document.querySelector('.pan-and-zoom-content') as HTMLElement;
  if (panelContainer !== null) {
    return panelContainer.clientHeight;
  } else {
    return getDetailsHeight();
  }
}

export class DragHandle implements m.ClassComponent<DragHandleAttrs> {
  private dragStartHeight = 0;
  private height = 0;
  private previousHeight = this.height;
  private resize: (height: number) => void = () => {};
  private isClosed = this.height <= 0;
  private isFullscreen = false;
  // We can't get real fullscreen height until the pan_and_zoom_handler exists.
  private fullscreenHeight = getDetailsHeight();
  private trash: Trash = new Trash();

  oncreate({dom, attrs}: m.CVnodeDOM<DragHandleAttrs>) {
    this.resize = attrs.resize;
    this.height = attrs.height;
    this.isClosed = this.height <= 0;
    this.fullscreenHeight = getFullScreenHeight();
    const elem = dom as HTMLElement;
    this.trash.add(new DragGestureHandler(
      elem,
      this.onDrag.bind(this),
      this.onDragStart.bind(this),
      this.onDragEnd.bind(this)));
  }

  onupdate({attrs}: m.CVnodeDOM<DragHandleAttrs>) {
    this.resize = attrs.resize;
    this.height = attrs.height;
    this.isClosed = this.height <= 0;
  }

  onremove(_: m.CVnodeDOM<DragHandleAttrs>) {
    this.trash.dispose();
  }

  onDrag(_x: number, y: number) {
    const newHeight =
        Math.floor(this.dragStartHeight + (DRAG_HANDLE_HEIGHT_PX / 2) - y);
    this.isClosed = newHeight <= 0;
    this.isFullscreen = newHeight >= this.fullscreenHeight;
    this.resize(newHeight);
    raf.scheduleFullRedraw();
  }

  onDragStart(_x: number, _y: number) {
    this.dragStartHeight = this.height;
  }

  onDragEnd() {}

  view({attrs}: m.CVnode<DragHandleAttrs>) {
    const {
      tabDropdownEntries,
      currentTabKey,
      tabs,
      onTabClick,
      onTabClose = () => {},
    } = attrs;

    const icon = this.isClosed ? UP_ICON : DOWN_ICON;
    const title = this.isClosed ? 'Show panel' : 'Hide panel';
    const renderTab = (tab: Tab) => {
      const {
        key,
        hasCloseButton = false,
      } = tab;
      const tag = (currentTabKey === key) ? '.tab[active]' : '.tab';
      return m(
        tag,
        {
          key,
          onclick: (event: Event) => {
            if (!event.defaultPrevented) {
              onTabClick(key);
            }
          },
        },
        m('span.pf-tab-title', tab.title),
        hasCloseButton && m(Button, {
          onclick: (event: Event) => {
            onTabClose(key);
            event.preventDefault();
          },
          minimal: true,
          compact: true,
          icon: 'close',
        }));
    };

    return m(
      '.handle',
      m('.tabs', tabs.map(renderTab)),
      m('.buttons',
        tabDropdownEntries && this.renderTabDropdown(tabDropdownEntries),
        m(
          Button,
          {
            onclick: () => {
              this.isClosed = false;
              this.isFullscreen = true;
              this.resize(this.fullscreenHeight);
              raf.scheduleFullRedraw();
            },
            title: 'Open fullscreen',
            disabled: this.isFullscreen,
            icon: 'vertical_align_top',
            minimal: true,
            compact: true,
          },
        ),
        m(
          Button,
          {
            onclick: () => {
              if (this.height === 0) {
                this.isClosed = false;
                if (this.previousHeight === 0) {
                  this.previousHeight = getDetailsHeight();
                }
                this.resize(this.previousHeight);
              } else {
                this.isFullscreen = false;
                this.isClosed = true;
                this.previousHeight = this.height;
                this.resize(0);
              }
              raf.scheduleFullRedraw();
            },
            title,
            icon,
            minimal: true,
            compact: true,
          },
        )));
  }

  private renderTabDropdown(entries: TabDropdownEntry[]) {
    return m(
      PopupMenu2,
      {
        trigger: m(Button, {
          minimal: true,
          compact: true,
          icon: 'add',
          disabled: entries.length === 0,
          title: 'Open tab',
        }),
      },
      entries.map((entry) => {
        return m(MenuItem, {
          key: entry.key,
          label: entry.title,
          onclick: () => entry.onClick(),
        });
      }),
    );
  }
}
