import { Injectable } from '@angular/core'
import { EventService } from './event.service'
import { globals } from '../_globals'
import { SasService } from './sas.service'
import { NavigationEnd, Router } from '@angular/router'
import { BehaviorSubject } from 'rxjs'
import { LoggerService } from './logger.service'
import { EnvironmentInfo } from '../system/models/environment-info.model'
import { LicenceService } from './licence.service'
import { AppSettingsService } from './app-settings.service'
import { AppThemes } from '../models/AppSettings'
import { RequestWrapperResponse } from '../models/request-wrapper/RequestWrapperResponse'
import { AppStoreService } from './app-store.service'

@Injectable()
export class AppService {
  public syssite = new BehaviorSubject<string[] | null>(null)
  private environmentInfo: EnvironmentInfo = {}

  constructor(
    private licenceService: LicenceService,
    private eventService: EventService,
    private sasService: SasService,
    private loggerService: LoggerService,
    private appSettingsService: AppSettingsService,
    private router: Router,
    private appStoreService: AppStoreService
  ) {
    this.subscribe()

    this.router.events.subscribe((val) => {
      if (val instanceof NavigationEnd) {
        if (val.url === '/deploy') {
          this.eventService.startupDataLoaded()
        }
      }
    })

    const appSettings = this.appSettingsService.settings.value

    if (!!appSettings.persistSelectedTheme) {
      if (appSettings.selectedTheme === AppThemes.light) {
        this.eventService.toggleDarkMode(false)
      } else if (appSettings.selectedTheme === AppThemes.dark) {
        this.eventService.toggleDarkMode(true)
      } else {
        // Fallback to light mode
        this.eventService.toggleDarkMode(false)
      }
    }
  }

  sasServiceInit() {
    this.sasService.sasServiceInit() //Code from constructor is put in this function inside SasService, because we first want to subscribe to emitters here before executing SasService init function
  }

  subscribe() {
    this.sasService.loadStartupServiceEmitter.subscribe(() => {
      this.startUpData()
    })

    this.sasService.requestSiteIdEmitter.subscribe((sysite: string) => {
      this.patchSyssite(sysite)
    })
  }

  public getEnvironmentInfo() {
    return this.environmentInfo
  }

  public patchSyssite(syssite: string) {
    let currentSyssite = this.syssite.getValue()

    if (currentSyssite) {
      if (!currentSyssite.includes(syssite)) {
        currentSyssite.push(syssite)
        this.syssite.next(currentSyssite)
      }
    }
  }

  public async startUpData() {
    let startupServiceError = false

    await this.sasService
      .request('public/startupservice', null)
      .then(async (res: RequestWrapperResponse) => {
        this.syssite.next([res.adapterResponse.SYSSITE])

        let missingProps: string[] = []

        if (
          !res.adapterResponse.globvars ||
          (res.adapterResponse.globvars && !res.adapterResponse.globvars[0])
        )
          missingProps.push('Globvars')
        if (!res.adapterResponse.sasdatasets) missingProps.push('Sasdatasets')
        if (!res.adapterResponse.saslibs) missingProps.push('Saslibs')
        if (!res.adapterResponse.xlmaps) missingProps.push('XLMaps')

        if (missingProps.length > 0) {
          startupServiceError = true
          this.eventService.showInfoModal(
            'Error',
            `${missingProps.join(', ')} are not present in the startupservice`
          )
          this.licenceService.isAppActivated.next(false)

          return
        }

        const dcAdapterSettings = this.appStoreService.getDcAdapterSettings()

        this.environmentInfo = {
          SYSSITE: res.adapterResponse.SYSSITE,
          SYSSCPL: res.adapterResponse.SYSSCPL,
          SYSTCPIPHOSTNAME: res.adapterResponse.SYSTCPIPHOSTNAME,
          SYSVLONG: res.adapterResponse.SYSVLONG,
          MEMSIZE: res.adapterResponse.MEMSIZE,
          SYSPROCESSMODE: res.adapterResponse.SYSPROCESSMODE,
          SYSHOSTNAME: res.adapterResponse.SYSHOSTNAME,
          SYSUSERID: res.adapterResponse.SYSUSERID,
          SYSHOSTINFOLONG: res.adapterResponse.SYSHOSTINFOLONG,
          SYSENCODING: res.adapterResponse.SYSENCODING,
          AUTOEXEC: res.adapterResponse.AUTOEXEC,
          ISADMIN: res.adapterResponse.globvars[0].ISADMIN,
          DC_ADMIN_GROUP: res.adapterResponse.globvars[0].DC_ADMIN_GROUP,
          APP_LOC: dcAdapterSettings?.appLoc
        }

        let libs = res.adapterResponse.sasdatasets
        let libGroup: any = {}
        let libsAndTables
        let libraries

        for (let lib of libs) {
          if (!libGroup[lib.LIBREF]) {
            libGroup[lib.LIBREF] = []
          }

          libGroup[lib.LIBREF].push(lib.DSN)
        }

        // Sidebar data structure
        let treeNodeTemp = JSON.parse(JSON.stringify(libGroup))
        let treeNode = []

        for (let library of Object.keys(treeNodeTemp)) {
          treeNode.push({
            LIBRARYREF: library,
            tables: treeNodeTemp[library]
          })
        }

        let treeNodeLibraries = treeNode
        // Sidebar data structure end

        libsAndTables = libGroup
        libraries = Object.keys(libGroup)

        if (libsAndTables !== undefined) {
          globals.editor.libsAndTables = libsAndTables
        }

        globals.xlmaps = res.adapterResponse.xlmaps.map((xlmap: any) => ({
          id: xlmap[0],
          description: xlmap[1],
          targetDS: xlmap[2]
        }))
        globals.editor.treeNodeLibraries = treeNodeLibraries
        globals.editor.libraries = libraries
        globals.editor.startupSet = true

        globals.dcLib = res.adapterResponse.globvars[0].DCLIB

        await this.licenceService.activation(res.adapterResponse)
      })
      .catch((err: any) => {
        startupServiceError = true
        this.eventService.showInfoModal(
          'Error',
          'There is an issue with startupservice response'
        )
        this.licenceService.isAppActivated.next(false)
      })

    this.loggerService.log(
      'Activated:',
      this.licenceService.isAppActivated.value
    )

    if (!startupServiceError) {
      this.eventService.startupDataLoaded()

      if (!this.licenceService.isAppActivated.value) {
        // If route is already on `licensing` page then we won't re route
        if (
          !this.router.url.includes('deploy') &&
          !this.router.url.includes('licensing')
        ) {
          this.router.navigateByUrl('/licensing/key?error=missing&force=true')
        }
      } else {
        if (this.router.url.includes('licensing'))
          this.router.navigateByUrl('/home')
      }
    }
  }
}
