import {
  Component,
  ChangeDetectionStrategy,
  inject,
  output,
  input,
  effect,
  DestroyRef
} from '@angular/core';

import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatDivider } from '@angular/material/divider';
import { CoordsPipe } from 'src/app/lib/pipes';
import { PopoverComponent } from './popover.component';
import { CompassComponent } from './compass.component';

import { AppFacade } from 'src/app/app.facade';
import { Buddies, SKVessel } from 'src/app/modules';
import { Convert } from 'src/app/lib/convert';
import { GeoUtils } from 'src/app/lib/geoutils';
import { Position } from 'src/app/types';
import { HttpErrorResponse } from '@angular/common/http';
import { AppIconDef, getAisIcon } from '../../icons';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

@Component({
  selector: 'vessel-popover',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [
    MatButtonModule,
    MatTooltipModule,
    MatIconModule,
    MatDivider,
    CoordsPipe,
    PopoverComponent,
    CompassComponent
  ],
  template: `
    <ap-popover
      [title]="_title"
      [mmsi]="vessel().mmsi"
      [icon]="_icon"
      [canClose]="canClose()"
      (closed)="handleClose()"
    >
      <div style="display:flex;">
        <div style="flex:1 1 auto;">
          @if (isActive()) {
            <button
              mat-icon-button
              (click)="handleMarkPosition()"
              matTooltip="Add Waypoint at vessel location"
            >
              <mat-icon>add_location</mat-icon>
            </button>
          } @else {
            <button
              mat-icon-button
              (click)="toggleFlag()"
              [matTooltip]="isFlagged ? 'Un-flag vessel' : 'Flag vessel'"
            >
              <mat-icon>{{ isFlagged ? 'clear_all' : 'flag' }}</mat-icon>
            </button>

            @if (!isSelf() && app.featureFlags().buddyList) {
              <button
                mat-icon-button
                (click)="toggleBuddy()"
                matTooltip="Is Buddy"
              >
                <mat-icon>{{
                  vessel().buddy ? 'group_remove' : 'group_add'
                }}</mat-icon>
              </button>
            }
            <button
              mat-icon-button
              (click)="focusVessel(true)"
              matTooltip="Focus vessel"
            >
              <mat-icon>center_focus_weak</mat-icon>
            </button>
          }
          @if (isActive() && !isSelf()) {
            <button
              mat-icon-button
              (click)="focusVessel(false)"
              matTooltip="Clear vessel focus"
            >
              <mat-icon>clear_all</mat-icon>
            </button>
          }
          @if (!isSelf()) {
            @let trackShown = app.isVesselTrackShown(vessel().id);
            <span
              [matTooltip]="
                app.config.vessels.aisShowTrack
                  ? 'Turn off &quot;Show All&quot; to enable'
                  : trackShown
                    ? 'Hide vessel track'
                    : 'Show vessel track'
              "
            >
              <button
                mat-icon-button
                (click)="toggleTrack()"
                [disabled]="app.config.vessels.aisShowTrack"
              >
                <mat-icon>{{ trackShown ? 'layers_clear' : 'route' }}</mat-icon>
              </button>
            </span>
          }
        </div>
        <div style="text-align:right;">
          <button
            mat-icon-button
            (click)="handleInfo()"
            matTooltip="Show Properties"
          >
            <mat-icon>info_outline</mat-icon>
          </button>
        </div>
      </div>
      <mat-divider></mat-divider>
      @if (vessel().callsignVhf) {
        <div style="display:flex;">
          <div style="font-weight:bold;">Callsign (VHF):</div>
          <div
            style="flex: 1 1 auto;text-align:right;"
            [innerText]="vessel().callsignVhf"
          ></div>
        </div>
      } @else if (vessel().callsignHf) {
        <div style="display:flex;">
          <div style="font-weight:bold;">Callsign (HF):</div>
          <div
            style="flex: 1 1 auto;text-align:right;"
            [innerText]="vessel().callsignHf"
          ></div>
        </div>
      }
      <div style="display:flex;">
        <div style="font-weight:bold;">Latitude:</div>
        <div
          style="flex: 1 1 auto;text-align:right;"
          [innerText]="
            position[1] | coords: app.config.units.positionFormat : true
          "
        ></div>
      </div>
      <div style="display:flex;">
        <div style="font-weight:bold;">Longitude:</div>
        <div
          style="flex: 1 1 auto;text-align:right;"
          [innerText]="position[0] | coords: app.config.units.positionFormat"
        ></div>
      </div>
      <div style="display:flex;">
        <div style="font-weight:bold;">Last Position:</div>
        <div style="flex: 1 1 auto;text-align:right;">
          {{ positionTimestamp }}
        </div>
      </div>
      @if (!isSelf()) {
        @if (vessel().distanceToSelf) {
          <div style="display:flex;">
            <div style="font-weight:bold;">Range:</div>
            <div style="flex: 1 1 auto;text-align:right;">
              {{ distToSelf }}
            </div>
          </div>
        }
        @if (vessel().closestApproach) {
          <div style="display:flex;">
            <div style="font-weight:bold;">CPA:</div>
            <div style="flex: 1 1 auto;text-align:right;">
              {{ cpa ?? '--' }}
            </div>
          </div>
          <div style="display:flex;">
            <div style="font-weight:bold;">TCPA:</div>
            <div style="flex: 1 1 auto;text-align:right;">
              {{ tcpa ?? '--' }}
            </div>
          </div>
        }
      }
      <div style="display:flex;">
        <div style="font-weight:bold;">Last Update:</div>
        <div style="flex: 1 1 auto;text-align:right;">
          {{ timeLastUpdate }} {{ timeAgo }}
        </div>
      </div>
      <div style="display:flex;flex-wrap:no-wrap;">
        <div style="width:120px;">
          <ap-compass
            [heading]="convert.radiansToDegrees(vessel().orientation)"
            [windtrue]="
              vessel().wind.direction !== null
                ? convert.radiansToDegrees(vessel().wind.direction)
                : null
            "
            [windapparent]="
              vessel().wind.awa !== null
                ? convert.radiansToDegrees(vessel().wind.awa)
                : null
            "
            [speed]="app.formatSpeed(vessel().sog)"
            [speedunits]="app.formattedSpeedUnits"
          >
          </ap-compass>
        </div>
        <div style="text-align:right; flex:auto;">
          &nbsp;<br />
          <div>
            <div style="border-right:olive 10px solid;padding-left: 5px;">
              <span style="font-weight:bold">
                Wind ({{ useMagnetic() ? 'M' : 'T' }}):</span
              >
            </div>
            <div style="flex: 1 1 auto;text-align:right;">
              {{ windSpeed(vessel().wind.tws, app.twsDisplayUnitPath()) }}
            </div>
          </div>
          <div>
            <div
              style="border-right:rgb(16, 75, 16) 10px solid;;padding-left: 5px;"
            >
              <span style="font-weight:bold;"> Wind (A):</span>
            </div>
            <div style="flex: 1 1 auto;text-align:right;">
              {{
                windSpeed(vessel().wind.aws, 'environment.wind.speedApparent')
              }}
            </div>
          </div>
        </div>
      </div>
    </ap-popover>
  `,
  styleUrls: []
})
export class VesselPopoverComponent {
  title = input<string>();
  vessel = input<SKVessel>();
  useMagnetic = input<string>();
  isActive = input<boolean>();
  isSelf = input<boolean>();
  canClose = input<boolean>();
  info = output<string>();
  closed = output<void>();
  focused = output<boolean>();
  markPosition = output<Position>();

  protected _title: string;
  protected _icon: AppIconDef;
  protected convert = Convert;
  protected timeLastUpdate: string;
  protected timeAgo: string; // last update in minutes ago
  protected speedUnits: string;
  protected distToSelf: string;
  protected cpa: string;
  protected tcpa: string;

  protected position: Position = [0, 0];
  protected positionTimestamp = '';
  protected isFlagged = false;

  protected app = inject(AppFacade);
  protected buddies = inject(Buddies);
  private destroyRef = inject(DestroyRef);

  /**
   * Format a wind speed (m/s) for display, honoring the per-path unit override
   * for `path` so wind speed can use a different unit than boat speed (#304).
   * Returns '--' when the value is unavailable.
   */
  protected windSpeed(value: number, path: string): string {
    return Number.isFinite(value)
      ? this.app.formatValueForDisplay(value, 'm/s', { path })
      : '--';
  }

  constructor() {
    effect(() => {
      if (!this.vessel()) {
        this.handleClose();
        return;
      }
      this.isFlagged = this.app.data.vessels.flagged.includes(this.vessel().id);
      this._title =
        this.title() ??
        this.vessel().name ??
        this.vessel().mmsi ??
        this.vessel().callsignVhf ??
        this.vessel().callsignHf;
      ('Vessel:');
      this._icon = this.vessel().type?.id
        ? getAisIcon(this.vessel().type?.id)
        : {
            name: 'directions_boat',
            svgIcon: undefined
          };
      this.position = [this.vessel().position[0], this.vessel().position[1]];
      this.position = GeoUtils.normaliseCoords(this.position);
      if (this.vessel().positionTimestamp) {
        const pts = new Date(this.vessel().positionTimestamp);
        this.positionTimestamp = `${pts.getHours()}:${(
          '00' + pts.getMinutes()
        ).slice(-2)}`;
      }

      this.timeLastUpdate = `${this.vessel().lastUpdated.getHours()}:${(
        '00' + this.vessel().lastUpdated.getMinutes()
      ).slice(-2)}`;
      const td =
        (new Date().valueOf() - this.vessel().lastUpdated.valueOf()) / 1000;
      this.timeAgo = td < 60 ? '' : `(${Math.floor(td / 60)} min ago)`;
      this.distToSelf = this.app.formatValueForDisplay(
        this.vessel().distanceToSelf,
        'm'
      );
      if (this.vessel().closestApproach) {
        if (typeof this.vessel().closestApproach.distance === 'number') {
          this.cpa = this.app.formatValueForDisplay(
            this.vessel().closestApproach.distance,
            'm'
          );
        }
        if (typeof this.vessel().closestApproach.timeTo === 'number') {
          this.tcpa = this.app.formatValueForDisplay(
            this.vessel().closestApproach.timeTo,
            's'
          );
        }
      }
    });
  }

  ngOnInit() {
    if (!this.vessel()) {
      this.handleClose();
      return;
    }
    this.isFlagged = this.app.data.vessels.flagged.includes(this.vessel().id);
  }

  handleMarkPosition() {
    this.markPosition.emit(this.vessel().position);
  }

  handleInfo() {
    this.info.emit(this.vessel().id);
  }

  focusVessel(setFocus: boolean) {
    this.removeFlag();
    this.focused.emit(setFocus);
  }

  toggleBuddy() {
    const urn = this.vessel().id.split('.').slice(1).join('.');
    if (this.vessel().buddy) {
      this.buddies
        .remove(urn)
        .pipe(takeUntilDestroyed(this.destroyRef))
        .subscribe(
          () => {
            //console.log('buddy revedmo:', urn);
            this.app.showMessage(`Buddy successfully removed.`, false, 3000);
          },
          (err: HttpErrorResponse) => {
            this.app.showMessage(`Error removing buddy!`, false, 3000);
          }
        );
    } else {
      const name =
        this.vessel().name ??
        this.vessel().mmsi ??
        this.vessel().callsignVhf ??
        urn.slice(-5);
      this.buddies
        .add(urn, name)
        .pipe(takeUntilDestroyed(this.destroyRef))
        .subscribe(
          () => {
            this.app.showMessage(`Buddy added (${name})`, false, 3000);
          },
          (err: HttpErrorResponse) => {
            this.app.showMessage(`Error adding buddy!(${name})`, false, 5000);
          }
        );
    }
  }

  toggleTrack() {
    this.app.toggleVesselTrack(this.vessel().id);
  }

  toggleFlag() {
    if (this.isFlagged) {
      this.removeFlag();
    } else {
      if (!this.app.data.vessels.flagged.includes(this.vessel().id)) {
        this.app.data.vessels.flagged = [this.vessel().id].concat(
          this.app.data.vessels.flagged
        );
      }
    }
    this.isFlagged = !this.isFlagged;
    this.closed.emit();
  }

  private removeFlag() {
    if (this.app.data.vessels.flagged.includes(this.vessel().id)) {
      this.app.data.vessels.flagged.splice(
        this.app.data.vessels.flagged.indexOf(this.vessel().id),
        1
      );
      this.app.data.vessels.flagged = [].concat(this.app.data.vessels.flagged);
    }
  }

  handleClose() {
    this.closed.emit();
  }
}
