// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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 {findRef} from '../base/dom_utils';
import {assertExists, assertTrue} from '../base/logging';
import {Time} from '../base/time';
import {Actions} from '../common/actions';
import {viewingOptions} from '../common/flamegraph_util';
import {
  CallsiteInfo,
  FlamegraphStateViewingOption,
  ProfileType,
} from '../common/state';
import {profileType} from '../controller/flamegraph_controller';
import {raf} from '../core/raf_scheduler';
import {Button} from '../widgets/button';
import {Icon} from '../widgets/icon';
import {Modal, ModalAttrs} from '../widgets/modal';
import {Popup} from '../widgets/popup';

import {Flamegraph, NodeRendering} from './flamegraph';
import {globals} from './globals';
import {debounce} from './rate_limiters';
import {Router} from './router';
import {getCurrentTrace} from './sidebar';
import {convertTraceToPprofAndDownload} from './trace_converter';
import {DurationWidget} from './widgets/duration';

const HEADER_HEIGHT = 30;

function toSelectedCallsite(c: CallsiteInfo|undefined): string {
  if (c !== undefined && c.name !== undefined) {
    return c.name;
  }
  return '(none)';
}

const RENDER_SELF_AND_TOTAL: NodeRendering = {
  selfSize: 'Self',
  totalSize: 'Total',
};
const RENDER_OBJ_COUNT: NodeRendering = {
  selfSize: 'Self objects',
  totalSize: 'Subtree objects',
};

export class FlamegraphDetailsPanel implements m.ClassComponent {
  private profileType?: ProfileType = undefined;
  private ts = Time.ZERO;
  private pids: number[] = [];
  private flamegraph: Flamegraph = new Flamegraph([]);
  private focusRegex = '';
  private updateFocusRegexDebounced = debounce(() => {
    this.updateFocusRegex();
  }, 20);
  private canvas?: HTMLCanvasElement;

  view() {
    const flamegraphDetails = globals.flamegraphDetails;
    if (flamegraphDetails.type !== undefined &&
        flamegraphDetails.start !== undefined &&
        flamegraphDetails.dur !== undefined &&
        flamegraphDetails.pids !== undefined &&
        flamegraphDetails.upids !== undefined) {
      this.profileType = profileType(flamegraphDetails.type);
      this.ts = Time.add(flamegraphDetails.start, flamegraphDetails.dur);
      this.pids = flamegraphDetails.pids;
      if (flamegraphDetails.flamegraph) {
        this.flamegraph.updateDataIfChanged(
          this.nodeRendering(), flamegraphDetails.flamegraph);
      }
      const height = flamegraphDetails.flamegraph ?
        this.flamegraph.getHeight() + HEADER_HEIGHT :
        0;
      return m(
        '.details-panel',
        this.maybeShowModal(flamegraphDetails.graphIncomplete),
        m('.details-panel-heading.flamegraph-profile',
          {onclick: (e: MouseEvent) => e.stopPropagation()},
          [
            m('div.options',
              [
                m('div.title',
                  this.getTitle(),
                  (this.profileType === ProfileType.MIXED_HEAP_PROFILE) &&
                        m(Popup,
                          {
                            trigger: m(Icon, {icon: 'warning'}),
                          },
                          m('',
                            {style: {width: '300px'}},
                            'This is a mixed java/native heap profile, free()s are not visualized. To visualize free()s, remove "all_heaps: true" from the config.')),
                  ':'),
                this.getViewingOptionButtons(),
              ]),
            m('div.details',
              [
                m('div.selected',
                  `Selected function: ${
                    toSelectedCallsite(
                      flamegraphDetails.expandedCallsite)}`),
                m('div.time',
                  `Snapshot time: `,
                  m(DurationWidget, {dur: flamegraphDetails.dur})),
                m('input[type=text][placeholder=Focus]', {
                  oninput: (e: Event) => {
                    const target = (e.target as HTMLInputElement);
                    this.focusRegex = target.value;
                    this.updateFocusRegexDebounced();
                  },
                  // Required to stop hot-key handling:
                  onkeydown: (e: Event) => e.stopPropagation(),
                }),
                (this.profileType === ProfileType.NATIVE_HEAP_PROFILE ||
                   this.profileType === ProfileType.JAVA_HEAP_SAMPLES) &&
                      m(Button, {
                        icon: 'file_download',
                        onclick: () => {
                          this.downloadPprof();
                        },
                      }),
              ]),
          ]),
        m(`canvas[ref=canvas]`, {
          style: `height:${height}px; width:100%`,
          onmousemove: (e: MouseEvent) => {
            const {offsetX, offsetY} = e;
            this.onMouseMove({x: offsetX, y: offsetY});
          },
          onmouseout: () => {
            this.onMouseOut();
          },
          onclick: (e: MouseEvent) => {
            const {offsetX, offsetY} = e;
            this.onMouseClick({x: offsetX, y: offsetY});
          },
        }),
      );
    } else {
      return m(
        '.details-panel',
        m('.details-panel-heading', m('h2', `Flamegraph Profile`)));
    }
  }


  private maybeShowModal(graphIncomplete?: boolean) {
    if (!graphIncomplete || globals.state.flamegraphModalDismissed) {
      return undefined;
    }
    return m(Modal, {
      title: 'The flamegraph is incomplete',
      vAlign: 'TOP',
      content:
          m('div', 'The current trace does not have a fully formed flamegraph'),
      buttons: [
        {
          text: 'Show the errors',
          primary: true,
          action: () => Router.navigate('#!/info'),
        },
        {
          text: 'Skip',
          action: () => {
            globals.dispatch(Actions.dismissFlamegraphModal({}));
            raf.scheduleFullRedraw();
          },
        },
      ],
    } as ModalAttrs);
  }

  private getTitle(): string {
    const profileType = this.profileType!;
    switch (profileType) {
    case ProfileType.MIXED_HEAP_PROFILE:
      return 'Mixed heap profile';
    case ProfileType.HEAP_PROFILE:
      return 'Heap profile';
    case ProfileType.NATIVE_HEAP_PROFILE:
      return 'Native heap profile';
    case ProfileType.JAVA_HEAP_SAMPLES:
      return 'Java heap samples';
    case ProfileType.JAVA_HEAP_GRAPH:
      return 'Java heap graph';
    case ProfileType.PERF_SAMPLE:
      return 'Profile';
    default:
      throw new Error('unknown type');
    }
  }

  private nodeRendering(): NodeRendering {
    if (this.profileType === undefined) {
      return {};
    }
    const profileType = this.profileType;
    const viewingOption: FlamegraphStateViewingOption =
        globals.state.currentFlamegraphState!.viewingOption;
    switch (profileType) {
    case ProfileType.JAVA_HEAP_GRAPH:
      if (viewingOption ===
            FlamegraphStateViewingOption.OBJECTS_ALLOCATED_NOT_FREED_KEY) {
        return RENDER_OBJ_COUNT;
      } else {
        return RENDER_SELF_AND_TOTAL;
      }
    case ProfileType.MIXED_HEAP_PROFILE:
    case ProfileType.HEAP_PROFILE:
    case ProfileType.NATIVE_HEAP_PROFILE:
    case ProfileType.JAVA_HEAP_SAMPLES:
    case ProfileType.PERF_SAMPLE:
      return RENDER_SELF_AND_TOTAL;
    default:
      const exhaustiveCheck: never = profileType;
      throw new Error(`Unhandled case: ${exhaustiveCheck}`);
    }
  }

  private updateFocusRegex() {
    globals.dispatch(Actions.changeFocusFlamegraphState({
      focusRegex: this.focusRegex,
    }));
  }

  getViewingOptionButtons(): m.Children {
    return m(
      'div',
      ...FlamegraphDetailsPanel.selectViewingOptions(
        assertExists(this.profileType)));
  }

  downloadPprof() {
    const engine = globals.getCurrentEngine();
    if (!engine) return;
    getCurrentTrace()
      .then((file) => {
        assertTrue(
          this.pids.length === 1,
          'Native profiles can only contain one pid.');
        convertTraceToPprofAndDownload(file, this.pids[0], this.ts);
      })
      .catch((error) => {
        throw new Error(`Failed to get current trace ${error}`);
      });
  }

  private changeFlamegraphData() {
    const data = globals.flamegraphDetails;
    const flamegraphData = data.flamegraph === undefined ? [] : data.flamegraph;
    this.flamegraph.updateDataIfChanged(
      this.nodeRendering(), flamegraphData, data.expandedCallsite);
  }

  oncreate({dom}: m.CVnodeDOM) {
    this.canvas = FlamegraphDetailsPanel.findCanvasElement(dom);
    // TODO(stevegolton): If we truely want to be standalone, then we shouldn't
    // rely on someone else calling the rafScheduler when the window is resized,
    // but it's good enough for now as we know the ViewerPage will do it.
    raf.addRedrawCallback(this.rafRedrawCallback);
  }

  onupdate({dom}: m.CVnodeDOM) {
    this.canvas = FlamegraphDetailsPanel.findCanvasElement(dom);
  }

  onremove(_vnode: m.CVnodeDOM) {
    raf.removeRedrawCallback(this.rafRedrawCallback);
  }

  private static findCanvasElement(dom: Element): HTMLCanvasElement|undefined {
    const canvas = findRef(dom, 'canvas');
    if (canvas && canvas instanceof HTMLCanvasElement) {
      return canvas;
    } else {
      return undefined;
    }
  }

  private rafRedrawCallback = () => {
    if (this.canvas) {
      const canvas = this.canvas;
      canvas.width = canvas.offsetWidth * devicePixelRatio;
      canvas.height = canvas.offsetHeight * devicePixelRatio;
      const ctx = canvas.getContext('2d');
      if (ctx) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.save();
        ctx.scale(devicePixelRatio, devicePixelRatio);
        const {offsetWidth: width, offsetHeight: height} = canvas;
        this.renderLocalCanvas(ctx, width, height);
        ctx.restore();
      }
    }
  };

  private renderLocalCanvas(
    ctx: CanvasRenderingContext2D, width: number, height: number) {
    this.changeFlamegraphData();
    const current = globals.state.currentFlamegraphState;
    if (current === null) return;
    const unit = current.viewingOption ===
                FlamegraphStateViewingOption
                  .SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY ||
            current.viewingOption ===
                FlamegraphStateViewingOption.ALLOC_SPACE_MEMORY_ALLOCATED_KEY ?
      'B' :
      '';
    this.flamegraph.draw(ctx, width, height, 0, 0, unit);
  }

  private onMouseClick({x, y}: {x: number, y: number}): boolean {
    const expandedCallsite = this.flamegraph.onMouseClick({x, y});
    globals.dispatch(Actions.expandFlamegraphState({expandedCallsite}));
    return true;
  }

  private onMouseMove({x, y}: {x: number, y: number}): boolean {
    this.flamegraph.onMouseMove({x, y});
    raf.scheduleFullRedraw();
    return true;
  }

  private onMouseOut() {
    this.flamegraph.onMouseOut();
    raf.scheduleFullRedraw();
  }

  private static selectViewingOptions(profileType: ProfileType) {
    const ret = [];
    for (const {option, name} of viewingOptions(profileType)) {
      ret.push(this.buildButtonComponent(option, name));
    }
    return ret;
  }

  private static buildButtonComponent(
    viewingOption: FlamegraphStateViewingOption, text: string) {
    const active =
        (globals.state.currentFlamegraphState !== null &&
         globals.state.currentFlamegraphState.viewingOption === viewingOption);
    return m(Button, {
      label: text,
      active,
      minimal: true,
      onclick: () => {
        globals.dispatch(Actions.changeViewFlamegraphState({viewingOption}));
      },
    });
  }
}
