// 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 {Actions} from '../common/actions';
import {translateState} from '../common/thread_state';
import {timeToCode, toNs} from '../common/time';
import {globals, SliceDetails, ThreadDesc} from './globals';
import {scrollToTrackAndTs} from './scroll_helper';
import {SlicePanel} from './slice_panel';

export class SliceDetailsPanel extends SlicePanel {
  view() {
    const sliceInfo = globals.sliceDetails;
    if (sliceInfo.utid === undefined) return;
    const threadInfo = globals.threads.get(sliceInfo.utid);

    return m(
        '.details-panel',
        m(
            '.details-panel-heading',
            m('h2.split', `Slice Details`),
            this.hasSchedLatencyInfo(sliceInfo) &&
                m('h2.split', 'Scheduling Latency'),
            ),
        this.renderDetails(sliceInfo, threadInfo));
  }

  private renderSchedLatencyInfo(sliceInfo: SliceDetails): m.Children {
    if (!this.hasSchedLatencyInfo(sliceInfo)) {
      return null;
    }
    return m(
        '.half-width-panel.slice-details-latency-panel',
        m('img.slice-details-image', {
          src: `${globals.root}assets/scheduling_latency.png`,
        }),
        this.renderWakeupText(sliceInfo),
        this.renderDisplayLatencyText(sliceInfo),
    );
  }

  private renderWakeupText(sliceInfo: SliceDetails): m.Children {
    if (sliceInfo.wakerUtid === undefined) {
      return null;
    }
    const threadInfo = globals.threads.get(sliceInfo.wakerUtid!);
    if (!threadInfo) {
      return null;
    }
    const timestamp = timeToCode(
        sliceInfo.wakeupTs! - globals.state.traceTime.startSec,
    );
    return m(
        '.slice-details-wakeup-text',
        m('', `Wakeup @ ${timestamp} on CPU ${sliceInfo.wakerCpu} by`),
        m('', `P: ${threadInfo.procName} [${threadInfo.pid}]`),
        m('', `T: ${threadInfo.threadName} [${threadInfo.tid}]`),
    );
  }

  private renderDisplayLatencyText(sliceInfo: SliceDetails): m.Children {
    if (sliceInfo.ts === undefined || sliceInfo.wakeupTs === undefined) {
      return null;
    }

    const latency = timeToCode(
        sliceInfo.ts - (sliceInfo.wakeupTs - globals.state.traceTime.startSec),
    );
    return m(
        '.slice-details-latency-text',
        m('', `Scheduling latency: ${latency}`),
        m('.text-detail',
          `This is the interval from when the task became eligible to run
        (e.g. because of notifying a wait queue it was suspended on) to
        when it started running.`),
    );
  }

  private hasSchedLatencyInfo({wakeupTs, wakerUtid}: SliceDetails): boolean {
    return wakeupTs !== undefined && wakerUtid !== undefined;
  }

  private renderDetails(sliceInfo: SliceDetails, threadInfo?: ThreadDesc):
      m.Children {
    if (!threadInfo || sliceInfo.ts === undefined ||
        sliceInfo.dur === undefined) {
      return null;
    } else {
      const tableRows = [
        m('tr',
          m('th', `Process`),
          m('td', `${threadInfo.procName} [${threadInfo.pid}]`)),
        m('tr',
          m('th', `Thread`),
          m('td',
            `${threadInfo.threadName} [${threadInfo.tid}]`,
            m('i.material-icons.grey',
              {onclick: () => this.goToThread(), title: 'Go to thread'},
              'call_made'))),
        m('tr', m('th', `Cmdline`), m('td', threadInfo.cmdline)),
        m('tr', m('th', `Start time`), m('td', `${timeToCode(sliceInfo.ts)}`)),
        m('tr',
          m('th', `Duration`),
          m('td', this.computeDuration(sliceInfo.ts, sliceInfo.dur))),
        (sliceInfo.threadDur === undefined ||
         sliceInfo.threadTs === undefined) ?
            '' :
            m('tr',
              m('th', 'Thread duration'),
              m('td',
                this.computeDuration(sliceInfo.threadTs, sliceInfo.threadDur))),
        m('tr', m('th', `Prio`), m('td', `${sliceInfo.priority}`)),
        m('tr',
          m('th', `End State`),
          m('td', translateState(sliceInfo.endState))),
        m('tr',
          m('th', `Slice ID`),
          m('td',
            (sliceInfo.id !== undefined) ? sliceInfo.id.toString() :
                                           'Unknown')),
      ];

      for (const [key, value] of this.getProcessThreadDetails(sliceInfo)) {
        if (value !== undefined) {
          tableRows.push(m('tr', m('th', key), m('td', value)));
        }
      }

      return m(
          '.details-table-multicolumn',
          m('table.half-width-panel', tableRows),
          this.renderSchedLatencyInfo(sliceInfo),
      );
    }
  }

  goToThread() {
    const sliceInfo = globals.sliceDetails;
    if (sliceInfo.utid === undefined) return;
    const threadInfo = globals.threads.get(sliceInfo.utid);

    if (sliceInfo.id === undefined || sliceInfo.ts === undefined ||
        sliceInfo.dur === undefined || sliceInfo.cpu === undefined ||
        threadInfo === undefined) {
      return;
    }

    let trackId: string|number|undefined;
    for (const track of Object.values(globals.state.tracks)) {
      if (track.kind === 'ThreadStateTrack' &&
          (track.config as {utid: number}).utid === threadInfo.utid) {
        trackId = track.id;
      }
    }

    if (trackId && sliceInfo.threadStateId) {
      globals.makeSelection(Actions.selectThreadState({
        id: sliceInfo.threadStateId,
        trackId: trackId.toString(),
      }));

      scrollToTrackAndTs(
          trackId, toNs(sliceInfo.ts + globals.state.traceTime.startSec), true);
    }
  }

  renderCanvas() {}
}
