import { Component, OnInit, Injector } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types';
import { NbToastrService, NbDialogService } from '@nebular/theme';
import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
import { allItems } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService/ApiService';
import { UpdatingComponent } from '../../UpdatingComponent';
import { LoggerService } from '../../services/LoggerService/logger.service';
import { FlashService } from '../../services/flash-service';

@Component({
  selector: 'raid',
  templateUrl: './raid.component.html',
})
export class FrontcraftRaidComponent
  extends UpdatingComponent
  implements OnInit {

  now = Date.now()
  canSignup = false
  isSignedup = false
  islate = false
  isTier = false
  reservesShown = true
  manageRaid
  changeReserve
  mySignup: (Signup & Character & Spec)

  raid: RaidData = <any>{
    participants: {
      Druid: [],
      Hunter: [],
      Mage: [],
      Paladin: [],
      Priest: [],
      Rogue: [],
      Shaman: [],
      Warlock: [],
      Warrior: [],
    },
    tanks: [],
    healers: [],
    tokens: {},
    tier: 'null'
  }
  tokens: { [itemname in string]: (Character & SRToken & Item)[] } = {}
  displayedtokens = {}
  search = ""

  constructor(
    injector: Injector,
    private api: IApiService,
    private route: ActivatedRoute,
    private router: Router,
    private dialogService: NbDialogService,
    private toast: NbToastrService,
    private flash: FlashService,
    private logger: LoggerService
  ) {
    super(injector)
  }

  ngOnInit() {
    this.manageRaid = this.api.get('manageRaid')
    this.changeReserve = this.api.get('changeReserve')
    const signupFeature = this.api.get('signup')

    if (signupFeature) {
      this.canSignup = true
    }
    this.refresh().then(() => {
      this.subscribe(String(this.raid.id), (data: RaidData) => this.display(data).then(_ =>
        this.flash.show()
      ))
    })
  }

  itemSelect = async (item) => {
    this.dialogService.open(FrontcraftBuyTokenComponent, {
      context: {
        item: item,
        signup: this.mySignup,
        tier: this.raid.tier,
        characterName: this.mySignup.charactername
      }
    }).onClose.subscribe(() => {
      this.refresh().then(() => {
        this.reservesShown = true
      })
    })
  }

  signup = async () => {
    const signupFeature = this.api.get('signup')
    if (!signupFeature) return

    this.dialogService.open(FrontcraftCharacerpickerComponent, {
      closeOnBackdropClick: true,
      closeOnEsc: true,
      context: {
        raid: this.raid,
      }
    }).onClose.subscribe(() => {
      this.refresh().then(() => {
        this.reservesShown = false
      })
    })
  }

  async archiveRaid(raid: Raid) {
    await this.manageRaid!.archiveRaid(raid)
    this.toast.show('Raid archived', 'Success', { status: 'success' })
    this.router.navigateByUrl('/frontcraft/archive/' + raid.id)
  }

  async startRaid(raid: Raid) {
    await this.manageRaid!.startRaid(raid)
    this.toast.show('Raid started', 'Success', { status: 'success' })
    this.router.navigateByUrl('/frontcraft/archive/' + raid.id)
  }

  async cancelRaid(raid: Raid) {
    await this.manageRaid!.cancelRaid(raid)
    this.toast.show('Raid cancelled', 'Success', { status: 'success' })
    this.router.navigateByUrl('/frontcraft/raids')
  }

  unsign = async () => {
    const signupFeature = this.api.get('signup')
    if (!signupFeature) return

    await signupFeature.unsign(this.api.getAuth().token.value, {
      ...this.mySignup,
      id: this.mySignup.characterid,
    }, this.raid)
    this.toast.show('Success', 'Unsigned', { status: 'success' })
  }

  setLate = async (value: boolean) => {
    const auth = this.api.getAuth()
    const signup = this.api.get('signup')
    if (!signup) return

    await signup.sign(auth.token.value, {
      ...this.mySignup,
      id: this.mySignup.characterid,
    }, this.raid, value, false, this.mySignup.memo)

    this.toast.show('Signup', 'Success', { status: 'success' })
  }

  setAbsent = async () => {
    const auth = this.api.getAuth()
    const signup = this.api.get('signup')
    if (!signup) return

    await signup.sign(auth.token.value, {
      ...this.mySignup,
      id: this.mySignup.characterid,
    }, this.raid, false, true, this.mySignup.memo)
    
    this.toast.show('Signup', 'Success', { status: 'success' })
  }

  adminUnsign = async (character: Character) => {
    const manage = this.api.get('manageRaid')
    if (!manage) return
    await manage.adminUnsign({
      ...character,
      id: character['characterid']
    }, this.raid)
  }

  refresh = async () => {
    const param = this.route.snapshot.paramMap.get('id');
    const raidManager = this.api.get('RaidManager')

    try {
      const raiddata = await raidManager.getRaidData(<any>{
        id: param
      })
      await this.display(raiddata)
    } catch (e) {
      this.router.navigate(["/"])
    }
  }

  display = async (raiddata: RaidData) => {
    this.isTier = allItems[raiddata.tier] != null

    this.raid = raiddata
    this.tokens = raiddata.tokens;

    [...raiddata.tanks, ...raiddata.healers, ...Object.values(raiddata.participants).flat()].forEach(p => {
      p['color'] = getClassColor(p.class)
      p['before'] = Number.parseInt(this.raid.start) - Date.parse(p.timestamp)
    })

    const user = this.api.getCurrentUser()
    const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)

    if (matchingSignup) {
      this.mySignup = matchingSignup
      this.isSignedup = true
      console.log(this.mySignup);
      
      this.mySignup['status'] = matchingSignup['absent'] ? 'Absent' : matchingSignup['benched'] ? 'Bench' : matchingSignup['late'] ? 'Late' : 'Attending'
    } else {
      this.isSignedup = false
      this.mySignup = null
    }

    this.changeSearch()
  }

  changeSearch() {
    if (!this.search || this.search == "") {
      this.displayedtokens = this.tokens
    } else {
      this.displayedtokens = {}
      Object.entries(this.tokens).forEach((e: [string /*itemname*/, (Character & SRToken & Item)[]]) => {
        const filteredTokens = e[1].filter(item => {
          return item.itemname.toLocaleLowerCase().includes(this.search.toLocaleLowerCase())
        })
        if (filteredTokens.length > 0)
          this.displayedtokens[e[0]] = filteredTokens
      })
    }
  }

  setBench(signup: Signup) {

    const manageRaid = this.api.get('manageRaid')
    if(manageRaid){
      const signupUpdated:Signup = {
        benched: !signup.benched,
        absent: false,
        late: false,
        characterid: signup.characterid,
        raidid: signup.raidid,
        timestamp: signup.timestamp,
        id: signup.id,
        memo: signup.memo
      }
      manageRaid.updateSignup(signupUpdated)
      .then(_ => this.refresh())
    }
  }

  adminSetAbsent(signup: Signup) {

    const manageRaid = this.api.get('manageRaid')
    if(manageRaid){
      const signupUpdated:Signup = {
        benched: false,
        absent: !signup.absent,
        late: false,
        characterid: signup.characterid,
        raidid: signup.raidid,
        timestamp: signup.timestamp,
        id: signup.id,
        memo: signup.memo
      }
      manageRaid.updateSignup(signupUpdated)
      .then(_ => this.refresh())
    }
  }

  increaseReserve(token: Character & SRToken & Item){
    this.changeReserve.increaseReserve(token, this.raid.id)
  }

  decreaseReserve(token: Character & SRToken & Item){  
    this.changeReserve.decreaseReserve(token, this.raid.id)
  }
}