import {Component, Inject, OnDestroy, OnInit} from "@angular/core";
import {AccountEvent, AccountInfo, AccountService} from "../bank/account/account.service";
import {PersonFirstRun, PersonService} from "./person.service";
import {HttpClient} from "@angular/common/http";
import * as _ from 'underscore'
import {BankService, DemurrageInfo} from "../bank/bank.service";
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from "@angular/material/dialog";
import {AppComponent} from "../app.component";
import {OrgInfo, OrgService} from "../org/org.service";
import {RxStompService} from "@stomp/ng2-stompjs";
import {Subscription} from "rxjs";
import * as jsPDF from 'jspdf/dist/jspdf.min'

@Component({
  selector: 'person-page',
  templateUrl: 'person.page.component.html',
  styleUrls: ['person.page.component.scss']
})
export class PersonPageComponent implements OnInit, OnDestroy {

  accounts: AccountInfo[] = []
  events: AccountEvent[] = []
  orgs: OrgInfo[] = []
  demurrage: DemurrageInfo
  eventBus: Subscription

  constructor(private app: AppComponent, private orgService: OrgService, private personService: PersonService, private accountService: AccountService, private bankService: BankService, private httpClient: HttpClient, private matDialog: MatDialog, private rxStompService: RxStompService) {
    app.setTitle("ЛИЧНЫЙ КАБИНЕТ")
  }

  ngOnDestroy(): void {
    this.eventBus.unsubscribe()
  }

  ngOnInit(): void {
    this.eventBus = this.rxStompService.watch(`/user/topic/exchange`).subscribe(msg => this.updateNow())
    this.updateNow()
  }

  updateNow(): void {
    this.personService.getCurrentPerson().subscribe(person => {
      this.orgService.getOrgsInfo(person.auth.id).subscribe(orgs => this.orgs = orgs);
      this.personService.getFirstRunInfo().subscribe(firstRun => {
        if (firstRun.firstRun) {
          this.showFirstRunDialog(firstRun)
        }
      });
      this.accountService.getAccountsInfo(person.auth.id).subscribe(accounts => {
        this.accounts = accounts
        let accountIds = accounts.map(e => e.id)
        this.accountService.getAccountEvents(person.auth.id).subscribe(events => {
          this.events = events.map(e => {
            if (_.indexOf(accountIds, e.info.from) >= 0) {
              e.info.direction = "from"
            } else if (_.indexOf(accountIds, e.info.to) >= 0) {
              e.info.direction = "to"
            } else {
              e.info.direction = "unknown"
            }
            return e;
          })
        })
      })
    })
    this.bankService.getNextDemurrage().subscribe(res => this.demurrage = res)
  }


  addAccount() {
    this.personService.getCurrentPerson().subscribe(person => this.accountService.addAccount(person.auth.id).subscribe(res => this.updateNow()))
  }

  iNeedMoney() {
    this.personService.getCurrentPerson().subscribe(person => this.httpClient.post(`/api/old/person/${person.auth.id}/givemoney`, {}).subscribe(res => this.updateNow()))
  }

  getTotatOverall(): number {
    return this.accounts.map(a => a.overall).reduce((total, x) => total + x, 0)
  }

  addPrivate() {
    this.personService.getCurrentPerson().subscribe(person => this.orgService.addPrivateToPerson(person.auth.id).subscribe(res => this.updateNow()))
  }

  joinPrivate() {

  }

  showDebitDialog(account: AccountInfo) {
    this.personService.getCurrentPerson().subscribe(person => {
      let ref = this.matDialog.open(PersonDebitDialogComponent, {
        width: '480px', height: '640px', data: <PersonDebitData>{
          accounts: this.accounts,
          account: account,
          personId: person.auth.id,
          once: true,
          time: 3
        }
      });
      ref.afterClosed().subscribe((res: any) => {
        //do nothing
      })
    })
  }

  showCreditDialog(account: AccountInfo) {
    this.personService.getCurrentPerson().subscribe(person => {
      let ref = this.matDialog.open(PersonCreditDialogComponent, {
        width: '480px', height: '400px', data: <PersonCreditData>{
          accounts: this.accounts,
          account: account,
          personId: person.auth.id
        }
      })
      ref.afterClosed().subscribe((res: any) => {
        if (res.action == 'create') {
          let data = <PersonCreditData>res.data
          this.httpClient.post(`/api/old/person/${person.auth.id}/account/${data.account.id}/credit/by-link/${data.code}`, {code: res.key, amount: data.amount}).subscribe((res: any) => {
            this.updateNow()
            console.log(`transaction done ${res.id}`)
          })
        }
      })
    });
  }

  showFirstRunDialog(fr: PersonFirstRun) {
    this.personService.getCurrentPerson().subscribe(person => {
      let ref = this.matDialog.open(PersonFirstRunDialogComponent, {
        width: '400px', height: '572px', data: fr
      })
    })
  }
}

@Component({
  selector: 'person-debit-dialog',
  templateUrl: 'person.debit.dialog.component.html',
  styleUrls: ['person.debit.dialog.component.scss']
})
export class PersonDebitDialogComponent {

  constructor(private httpClient: HttpClient, private dialogRef: MatDialogRef<PersonDebitDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: PersonDebitData) {
    this.dialogRef.beforeClosed().subscribe(res => {

    })
  }

  getCodeUrl(code: string): string {
    let proto = window.location.port != "443" ? "http" : "https";
    let port = window.location.port == "80" ? "" : window.location.port == "443" ? "" : window.location.port
    return `${proto}://${window.location.host}${port}/c/${code}`
  }

  getCode() {
    this.httpClient.post(`/api/old/person/${this.data.personId}/account/${this.data.account.id}/debit-by-link`, {amount: this.data.amount, once: this.data.once, time: this.data.time}).subscribe((res: any) => {
      this.data.code = res.code
    })
  }
}

@Component({
  selector: 'person-credit-dialog',
  templateUrl: 'person.credit.dialog.component.html',
  styleUrls: ['person.credit.dialog.component.scss']
})
export class PersonCreditDialogComponent {

  key: string
  keyOk: number
  codeOk: number

  constructor(private httpClient: HttpClient, private dialogRef: MatDialogRef<PersonDebitDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: PersonCreditData) {
    this.dialogRef.beforeClosed().subscribe(res => {

    })
  }

  checkCode(x: string) {
    this.httpClient.get(`/api/old/person/${this.data.personId}/get-credit-link/${x}`).subscribe((res: any) => {
      if (res.ok) {
        this.codeOk = 1
        if (res.amount > 0) this.data.amount = res.amount
      } else {
        this.codeOk = 0
      }
      this.data.code = x;
    }, error => {
      this.codeOk = 0
    })
  }

  checkKey(x: string) {
    this.httpClient.post(`/api/old/person/${this.data.personId}/check6`, {key: x}).subscribe((res: any) => {
      if (res.ok) {
        this.keyOk = 1
      } else {
        this.keyOk = 0
      }
      this.key = x
    }, error => {
      this.keyOk = 0
    });
  }

}

@Component({
  selector: 'person-first-run-dialog',
  templateUrl: 'person.first.run.dialog.component.html',
  styleUrls: []
})
export class PersonFirstRunDialogComponent {

  constructor(private dialogRef: MatDialogRef<PersonDebitDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: PersonFirstRun) {

  }

  getCodes() {
    var doc = new jsPDF()

    doc.text("FG recovery code list", 10, 10)

    this.data.codes.forEach((c, i) => {
      doc.text(`${i + 1}) ${c}`, 10, 20 + i * 10)
    })

    doc.save('fg-codes.pdf')
  }
}

abstract class PersonAccountData {
  account: AccountInfo
  accounts: AccountInfo[]
  personId: string
}

export class PersonCreditData extends PersonAccountData {
  code: string
  amount: number
}

export class PersonDebitData extends PersonAccountData {
  amount: number
  time: number
  once: boolean
  limited: boolean
  code: string
}
