/*
 * Copyright (C) 2022 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 {Component, ElementRef, EventEmitter, Inject, Input, Output} from '@angular/core';
import {TRACE_INFO} from 'app/trace_info';
import {PersistentStore} from 'common/persistent_store';
import {View, Viewer, ViewType} from 'viewers/viewer';
interface Tab extends View {
  addedToDom: boolean;
}
@Component({
  selector: 'trace-view',
  template: `
    
    
    
    
  `,
  styles: [
    `
      .overlay {
        z-index: 10;
        position: fixed;
        top: 0px;
        left: 0px;
        width: 100%;
        height: 100%;
        pointer-events: none;
      }
      .overlay .draggable-container {
        position: absolute;
        right: 0;
        top: 20vh;
      }
      .header-items-wrapper {
        display: flex;
        flex-direction: row;
        justify-content: space-between;
      }
      .tabs-navigation-bar {
        height: 100%;
      }
      .trace-view-content {
        height: 100%;
        overflow: auto;
      }
    `,
  ],
})
export class TraceViewComponent {
  @Input() viewers!: Viewer[];
  @Input() store!: PersistentStore;
  @Output() downloadTracesButtonClick = new EventEmitter();
  @Output() activeViewChanged = new EventEmitter();
  TRACE_INFO = TRACE_INFO;
  private elementRef: ElementRef;
  tabs: Tab[] = [];
  private currentActiveTab: undefined | Tab;
  constructor(@Inject(ElementRef) elementRef: ElementRef) {
    this.elementRef = elementRef;
  }
  ngOnChanges() {
    this.renderViewsTab();
    this.renderViewsOverlay();
  }
  onTabClick(tab: Tab) {
    this.showTab(tab);
  }
  private renderViewsTab() {
    this.tabs = this.viewers
      .map((viewer) => viewer.getViews())
      .flat()
      .filter((view) => view.type === ViewType.TAB)
      .map((view) => {
        return {
          type: view.type,
          htmlElement: view.htmlElement,
          title: view.title,
          addedToDom: false,
          dependencies: view.dependencies,
          traceType: view.traceType,
        };
      });
    this.tabs.forEach((tab) => {
      // TODO: setting "store" this way is a hack.
      //       Store should be part of View's interface.
      (tab.htmlElement as any).store = this.store;
    });
    if (this.tabs.length > 0) {
      this.showTab(this.tabs[0]);
    }
  }
  private renderViewsOverlay() {
    const views: View[] = this.viewers
      .map((viewer) => viewer.getViews())
      .flat()
      .filter((view) => view.type === ViewType.OVERLAY);
    if (views.length > 1) {
      throw new Error(
        'Only one overlay view is supported. To allow more overlay views, either create more than' +
          ' one draggable containers in this component or move the cdkDrag directives into the' +
          " overlay view when the new Angular's directive composition API is available" +
          ' (https://github.com/angular/angular/issues/8785).'
      );
    }
    views.forEach((view) => {
      view.htmlElement.style.pointerEvents = 'all';
      const container = this.elementRef.nativeElement.querySelector(
        '.overlay .draggable-container'
      )!;
      container.appendChild(view.htmlElement);
    });
  }
  private showTab(tab: Tab) {
    if (this.currentActiveTab) {
      this.currentActiveTab.htmlElement.style.display = 'none';
    }
    if (!tab.addedToDom) {
      // Workaround for b/255966194:
      // make sure that the first time a tab content is rendered
      // (added to the DOM) it has style.display == "". This fixes the
      // initialization/rendering issues with cdk-virtual-scroll-viewport
      // components inside the tab contents.
      const traceViewContent = this.elementRef.nativeElement.querySelector('.trace-view-content')!;
      traceViewContent.appendChild(tab.htmlElement);
      tab.addedToDom = true;
    } else {
      tab.htmlElement.style.display = '';
    }
    this.currentActiveTab = tab;
    this.activeViewChanged.emit(tab);
  }
  isCurrentActiveTab(tab: Tab) {
    return tab === this.currentActiveTab;
  }
}