// Copyright (C) 2023 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 {classNames} from '../base/classnames';
import {hasChildren} from '../base/mithril_utils';

import {scheduleFullRedraw} from './raf';

// Heirachical tree layout with left and right values.
// Right and left values of the same indentation level are horizontally aligned.
// Example:
// foo    bar
//  ├ baz  qux
//  └ quux corge
//    ├ looong_left aaa
//    └ a           bbb
// grault garply

interface TreeAttrs {
  // Space delimited class list applied to our tree element.
  className?: string;
}

export class Tree implements m.ClassComponent<TreeAttrs> {
  view({attrs, children}: m.Vnode<TreeAttrs>): m.Children {
    const {
      className = '',
    } = attrs;

    const classes = classNames(
      className,
    );

    return m('.pf-tree', {class: classes}, children);
  }
}

interface TreeNodeAttrs {
  // Content to display in the left hand column.
  // If omitted, this side will be blank.
  left?: m.Children;
  // Content to display in the right hand column.
  // If omitted, this side will be left blank.
  right?: m.Children;
  // Content to display in the right hand column when the node is collapsed.
  // If omitted, the value of `right` shall be shown when collapsed instead.
  // If the node has no children, this value is never shown.
  summary?: m.Children;
  // Whether this node is collapsed or not.
  // If omitted, collapsed state 'uncontrolled' - i.e. controlled internally.
  collapsed?: boolean;
  // Whether the node should start collapsed or not, default: false.
  startsCollapsed?: boolean;
  loading?: boolean;
  showCaret?: boolean;
  // Optional icon to show to the left of the text.
  // If this node contains children, this icon is ignored.
  icon?: string;
  // Called when the collapsed state is changed, mainly used in controlled mode.
  onCollapseChanged?: (collapsed: boolean, attrs: TreeNodeAttrs) => void;
}

export class TreeNode implements m.ClassComponent<TreeNodeAttrs> {
  private collapsed;

  constructor({attrs}: m.CVnode<TreeNodeAttrs>) {
    this.collapsed = attrs.startsCollapsed ?? false;
  }

  view(vnode: m.CVnode<TreeNodeAttrs>): m.Children {
    const {children, attrs, attrs: {left, onCollapseChanged = () => {}}} =
        vnode;
    return m(
      '.pf-tree-node',
      {
        class: classNames(this.getClassNameForNode(vnode)),
      },
      m('span.pf-tree-gutter', {
        onclick: () => {
          this.collapsed = !this.isCollapsed(vnode);
          onCollapseChanged(this.collapsed, attrs);
          scheduleFullRedraw();
        },
      }),
      m(
        '.pf-tree-content',
        m('.pf-tree-left', left),
        this.renderRight(vnode),
      ),
      hasChildren(vnode) &&
            [
              m('span.pf-tree-indent-gutter'),
              m('.pf-tree-children', children),
            ],
    );
  }

  private getClassNameForNode(vnode: m.CVnode<TreeNodeAttrs>) {
    const {
      loading = false,
      showCaret = false,
    } = vnode.attrs;
    if (loading) {
      return 'pf-loading';
    } else if (hasChildren(vnode) || showCaret) {
      if (this.isCollapsed(vnode)) {
        return 'pf-collapsed';
      } else {
        return 'pf-expanded';
      }
    } else {
      return undefined;
    }
  }

  private renderRight(vnode: m.CVnode<TreeNodeAttrs>) {
    const {attrs: {right, summary}} = vnode;
    if (hasChildren(vnode) && this.isCollapsed(vnode)) {
      return m('.pf-tree-right', summary ?? right);
    } else {
      return m('.pf-tree-right', right);
    }
  }

  private isCollapsed({attrs}: m.Vnode<TreeNodeAttrs>): boolean {
    // If collapsed is omitted, use our local collapsed state instead.
    const {
      collapsed = this.collapsed,
    } = attrs;

    return collapsed;
  }
}

export function dictToTreeNodes(dict: {[key: string]: m.Child}): m.Child[] {
  const children: m.Child[] = [];
  for (const key of Object.keys(dict)) {
    if (dict[key] == undefined) {
      continue;
    }
    children.push(m(TreeNode, {
      left: key,
      right: dict[key],
    }));
  }
  return children;
}

// Create a flat tree from a POJO
export function dictToTree(dict: {[key: string]: m.Child}): m.Children {
  return m(Tree, dictToTreeNodes(dict));
}
interface LazyTreeNodeAttrs {
  // Same as TreeNode (see above).
  left?: m.Children;
  // Same as TreeNode (see above).
  right?: m.Children;
  // Same as TreeNode (see above).
  icon?: string;
  // Same as TreeNode (see above).
  summary?: m.Children;
  // A callback to be called when the TreeNode is expanded, in order to fetch
  // child nodes.
  // The callback must return a promise to a function which returns m.Children.
  // The reason the promise must return a function rather than the actual
  // children is to avoid storing vnodes between render cycles, which is a bug
  // in Mithril.
  fetchData: () => Promise<() => m.Children>;
  // Whether to unload children on collapse.
  // Defaults to false, data will be kept in memory until the node is destroyed.
  unloadOnCollapse?: boolean;
}

// This component is a TreeNode which only loads child nodes when it's expanded.
// This allows us to represent huge trees without having to load all the data
// up front, and even allows us to represent infinite or recursive trees.
export class LazyTreeNode implements m.ClassComponent<LazyTreeNodeAttrs> {
  private collapsed: boolean = true;
  private loading: boolean = false;
  private renderChildren?: () => m.Children;

  view({attrs}: m.CVnode<LazyTreeNodeAttrs>): m.Children {
    const {
      left,
      right,
      icon,
      summary,
      fetchData,
      unloadOnCollapse = false,
    } = attrs;

    return m(
      TreeNode,
      {
        left,
        right,
        icon,
        summary,
        showCaret: true,
        loading: this.loading,
        collapsed: this.collapsed,
        onCollapseChanged: (collapsed) => {
          if (collapsed) {
            if (unloadOnCollapse) {
              this.renderChildren = undefined;
            }
          } else {
            // Expanding
            if (this.renderChildren) {
              this.collapsed = false;
              scheduleFullRedraw();
            } else {
              this.loading = true;
              fetchData().then((result) => {
                this.loading = false;
                this.collapsed = false;
                this.renderChildren = result;
                scheduleFullRedraw();
              });
            }
          }
          this.collapsed = collapsed;
          scheduleFullRedraw();
        },
      },
      this.renderChildren && this.renderChildren());
  }
}
