import { ViewFlags } from '@angular/compiler/src/core';
import { Component, Input, OnInit, OnChanges, ViewChild } from '@angular/core';
import { MatButton } from '@angular/material/button';
import { MatExpansionPanel } from '@angular/material/expansion';
import { MatTableDataSource } from '@angular/material/table';
import { AccountEntryCategoryService, AccountEntryService, AccountService } from '../data-object-service';
import { Account, AccountEntry, AccountEntryCategory, NULL_AccountEntry } from '../data-objects';
import { ExtApiService } from '../ext-data-object-service';
import { Saldo } from '../ext-data-objects';
import { MessageService } from '../message.service';



interface DN_AccountEntry {
  rawAccountEntry: AccountEntry
  accountEntryCategory: string
  overheadRelevant: boolean
}


@Component({
  selector: 'app-account',
  templateUrl: './account.component.html',
  styleUrls: ['./account.component.css']
})
export class AccountComponent implements OnInit {

  @Input() selectedAccountId: number
  @Input() shallBeRentPayment: boolean
  @ViewChild('addAccountEntryButton') addAccountEntryButton: MatButton

  account: Account
  accountEntries: DN_AccountEntry[]
  accountEntriesDataSource: MatTableDataSource<DN_AccountEntry>
  accountEntriesDisplayedColumns: string[] = [ "description", "amount", "createdAt", "category", "overhead_relevant" ]
  saldo: Saldo

  accountEntryCategories: AccountEntryCategory[]
  accountEntryCategoriesMap: Map<number, AccountEntryCategory>
  accountEntryCategoriesInverseMap: Map<string, AccountEntryCategory>



  constructor(
    private accountService: AccountService,
    private accountEntryService: AccountEntryService,
    private extApiService: ExtApiService,
    private accountEntryCategoryService: AccountEntryCategoryService,
    private messageService: MessageService
  ) { }


  async getAccount(): Promise<void> {
    try {
      if (this.selectedAccountId) {
        this.messageService.add(`Trying to load account ${this.selectedAccountId} and entries`)
        this.account = await this.accountService.getAccount(this.selectedAccountId)
        this.messageService.add(`Account: ${JSON.stringify(this.account, undefined, 4)}`)
        this.getAccountEntries()
      }
    } catch (err) {
      this.messageService.add(`Error in getAccount: ${JSON.stringify(err, undefined, 4)}`)
    }
  }

  async getAccountEntries(): Promise<void> {
    try {
      const rawAccountEntries = await this.accountEntryService.getAccountEntrysByAccount(this.selectedAccountId)
      rawAccountEntries.reverse()
      this.messageService.add(`AccountEntries: ${JSON.stringify(rawAccountEntries, undefined, 4)}`)
      this.accountEntries = []
      for (let f of rawAccountEntries) {
        this.accountEntries.push({
          rawAccountEntry: f,
          accountEntryCategory: this.accountEntryCategoriesMap.get(f.account_entry_category).description,
          overheadRelevant: this.accountEntryCategoriesMap.get(f.account_entry_category).overhead_relevant
        })
      }

      this.accountEntriesDataSource = new MatTableDataSource<DN_AccountEntry>(this.accountEntries)
      this.saldo = await this.extApiService.getAccountSaldo(this.selectedAccountId)
    } catch (err) {
      throw err

      this.messageService.add(`Error in getAccountEntries: ${JSON.stringify(err, undefined, 4)}`)
    }
  }

  async addAccountEntry(formData: any): Promise<void> {
    try {
      this.addAccountEntryButton.disabled = true
      this.messageService.add(`${JSON.stringify(formData.value, undefined, 4)}`)
      let newAccountEntry: AccountEntry = {
        description: formData.value.description,
        account: this.account.id,
        created_at: formData.value.createdAt,
        amount: formData.value.amount,
        id: 0,
        account_entry_category: 0
      }

      if (this.shallBeRentPayment) {
        newAccountEntry.account_entry_category = this.accountEntryCategoriesInverseMap.get('Mietzahlung').id
        this.messageService.add(`shall be rentpayment, category is ${newAccountEntry.account_entry_category}`)
      } else {
        newAccountEntry.account_entry_category = formData.value.category
        this.messageService.add(`category is ${newAccountEntry.account_entry_category}`)
      }

      this.messageService.add(`addAccountEntry: ${ JSON.stringify(newAccountEntry, undefined, 4) }`)
      newAccountEntry = await this.accountEntryService.postAccountEntry(newAccountEntry)
      this.messageService.add(`New accountEntry created: ${newAccountEntry.id}`)

      this.getAccountEntries()
    } catch (err) {
      this.messageService.add(`Error in addAccountEntry: ${JSON.stringify(err, undefined, 4)}`)
    } finally {
      formData.reset()
      this.addAccountEntryButton.disabled = false
    }
  }

  async getAccountEntryCategories(): Promise<void> {
    try {
      this.accountEntryCategories = await this.accountEntryCategoryService.getAccountEntryCategorys()
      this.accountEntryCategoriesMap = new Map<number, AccountEntryCategory>()
      this.accountEntryCategoriesInverseMap = new Map<string, AccountEntryCategory>()
      for (let p of this.accountEntryCategories) {
        this.accountEntryCategoriesMap.set(p.id, p)
        this.accountEntryCategoriesInverseMap.set(p.description, p)
      }

      this.messageService.add(`getAccountEntryCategories: ${JSON.stringify(this.accountEntryCategories, undefined, 4)}`)
    } catch (err) {
      this.messageService.add(`Error in getAccountEntryCategories: ${JSON.stringify(err, undefined, 4)}`)
    }
  }

  private async init(): Promise<void> {
    this.messageService.add(`AccountComponent.init, account: ${this.selectedAccountId}`)
    this.getAccount()
    await this.getAccountEntryCategories()
  }

  ngOnInit(): void {
    this.init()
  }

  ngOnChanges(): void {
    this.init()
  }


}