import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core';
import {Mix, MixMaterial, Recipe} from "../../../shared/model/recipe.model";
import {Subject} from "rxjs";
import {SubscribingComponent} from "../../../shared/components/subscribing.component";
import {convertMixMaterialQuantity, UNIT_MILLILITER} from "../../../shared/units";
import {ActivatedRoute, Router} from "@angular/router";
import {PtouchPrinter} from "../../ptouchPrint"
import {ConfirmBoxComponent} from "../../../shared/components/confirm-box/confirm-box.component";

@Component({
  selector: 'cre-mix-table',
  templateUrl: './mix-table.component.html',
  styleUrls: ['./mix-table.component.sass']
})
export class MixTableComponent extends SubscribingComponent {
  private readonly COLUMNS = ['material', 'materialType', 'quantity', 'quantityCalculated', 'quantityUnits']
  private readonly COLUMNS_STATIC = ['material', 'materialType', 'quantityStatic', 'quantityUnits']

  @ViewChild('printingConfirmBox') printingConfirmBox: ConfirmBoxComponent

  @Input() mix: Mix
  @Input() recipe: Recipe
  @Input() units$: Subject<string>
  @Input() deductErrorBody
  @Input() editing: boolean
  @Input() printingError = 2
  @Output() locationChange = new EventEmitter<{ id: number, location: string }>()
  @Output() quantityChange = new EventEmitter<{ id: number, materialId: number, quantity: number }>()
  @Output() deduct = new EventEmitter<void>()
  @Output() printingErrorChange = new EventEmitter<number>()

  mixColumns = this.COLUMNS
  units = UNIT_MILLILITER
  computedQuantities: { id: number, percents: boolean, quantity: number }[] = []

  // BPac printer
  printer: PtouchPrinter | null

  constructor(
    router: Router,
    activatedRoute: ActivatedRoute
  ) {
    super(activatedRoute, router)
  }

  ngOnInit() {
    super.ngOnInit();

    if (this.editing) {
      this.mixColumns = this.COLUMNS_STATIC
    }

    this.mix.mixMaterials.forEach(m => this.computedQuantities.push({
      id: m.id,
      percents: m.material.materialType.usePercentages,
      quantity: m.quantity
    }))

    this.subscribe(
      this.units$,
      {
        next: u => this.convertQuantities(u)
      }
    )
  }

  changeLocation(event: any) {
    this.locationChange.emit({id: this.mix.id, location: event.target.value})
  }

  changeQuantity(event: any, mixMaterial: MixMaterial, isTotal = false) {
    const newQuantity = parseInt(event.target.value)
    let ratio = 1
    if (!isTotal) {
      const originalQuantity = this.getComputedQuantity(mixMaterial.id)
      ratio = newQuantity / originalQuantity.quantity
    } else {
      ratio = newQuantity / this.getTotalQuantity()
    }
    this.computedQuantities.forEach((q, i) => {
      if (!q.percents) {
        q.quantity *= ratio
      }
      this.emitQuantityChangeEvent(i)
    })
  }

  getComputedQuantityRounded(mixMaterial: MixMaterial): number {
    return this.round(this.getComputedQuantity(mixMaterial.id).quantity)
  }

  getTotalQuantity(index: number = -1): number {
    if (index === -1) index = this.computedQuantities.length - 1
    let totalQuantity = 0
    for (let i = 0; i <= index; i++) {
      totalQuantity += this.calculateQuantity(i)
    }
    return totalQuantity
  }

  getCalculatedQuantity(mixMaterial: MixMaterial, index: number): string {
    const totalQuantity = this.round(this.getTotalQuantity(index))
    const addedQuantity = this.round(this.calculateQuantity(index))
    return `<span class="mix-calculated-quantity">+${addedQuantity}</span> <span class="mix-calculated-quantity">(${totalQuantity})</span>`
  }

  isInLowQuantity(materialId: number): boolean {
    return this.deductErrorBody[this.mix.id] && this.deductErrorBody[this.mix.id].indexOf(materialId) >= 0
  }

  round(quantity: number): number {
    return Math.round(quantity * 1000) / 1000
  }

  async print() {
    const base = this.mix.mixMaterials
      .map(ma => ma.material)
      .filter(m => m.materialType.name === 'Base')[0]
    if (!base) {
      this.printingErrorChange.emit(98)
      return
    }
    this.printer = new PtouchPrinter({
      template: "Couleur",
      lines: [
        {name: "color", value: this.recipe.name},
        {name: "banner", value: this.recipe.company.name},
        {name: "base", value: base.name},
        {name: "description", value: this.recipe.description}
      ]
    })
    const errorCode = await this.printer.print()
    this.printingErrorChange.emit(errorCode)
  }

  private emitQuantityChangeEvent(index: number) {
    this.quantityChange.emit({
      id: this.mix.id,
      materialId: this.computedQuantities[index].id,
      quantity: this.calculateQuantity(index)
    })
  }

  private convertQuantities(newUnit: string) {
    this.computedQuantities.forEach(q => convertMixMaterialQuantity(q, this.units, newUnit))
    this.units = newUnit
  }

  private getComputedQuantity(id: number): any {
    return this.computedQuantities.filter(q => q.id == id)[0]
  }

  private calculateQuantity(index: number): number {
    const computedQuantity = this.computedQuantities[index]
    if (!computedQuantity.percents) {
      return computedQuantity.quantity
    }
    return this.computedQuantities[0].quantity * (computedQuantity.quantity / 100)
  }
}
