import {
  UILanguage, UITheme, Styles, Controls,
  CaptionItem, FullConfig, SoftwareLogItem
} from '../types'
import { Log } from './Log'
import { app, BrowserWindow } from 'electron'
import { passwordMaskingForObject } from './UtilsFunc'
import * as path from 'path'
import * as fs from 'fs'
import * as os from 'os'

interface CaptionTranslation {
  time_s: string,
  translation: string
}

function getDesktopPath() {
  const homeDir = os.homedir()
  return path.join(homeDir, 'Desktop')
}

const defaultStyles: Styles = {
  lineNumber: 1,
  lineBreak: 1,
  fontFamily: 'sans-serif',
  fontSize: 24,
  fontColor: '#000000',
  fontWeight: 4,
  background: '#dbe2ef',
  opacity: 80,
  showPreview: true,
  transDisplay: true,
  transFontFamily: 'sans-serif',
  transFontSize: 24,
  transFontColor: '#000000',
  transFontWeight: 4,
  textShadow: false,
  offsetX: 2,
  offsetY: 2,
  blur: 0,
  textShadowColor: '#ffffff'
};

const defaultControls: Controls = {
  sourceLang: 'en',
  targetLang: 'zh',
  transModel: 'ollama',
  ollamaName: 'qwen2.5:0.5b',
  ollamaUrl: 'http://localhost:11434',
  ollamaApiKey: '',
  engine: 'gummy',
  audio: 0,
  engineEnabled: false,
  API_KEY: '',
  voskModelPath: '',
  sosvModelPath: '',
  glmUrl: 'https://open.bigmodel.cn/api/paas/v4/audio/transcriptions',
  glmModel: 'glm-asr-2512',
  glmApiKey: '',
  recordingPath: getDesktopPath(),
  translation: true,
  recording: false,
  customized: false,
  customizedApp: '',
  customizedCommand: '',
  startTimeoutSeconds: 30
};


class AllConfig {
  captionWindowWidth: number = 900;

  uiLanguage: UILanguage = 'zh';
  leftBarWidth: number = 8;
  uiTheme: UITheme = 'system';
  uiColor: string = '#1677ff';
  styles: Styles = {...defaultStyles};
  controls: Controls = {...defaultControls};
  
  lastLogIndex: number = -1;
  captionLog: CaptionItem[] = [];

  constructor() {}

  public readConfig() {
    const configPath = path.join(app.getPath('userData'), 'config.json')
    if(fs.existsSync(configPath)){
      Log.info('Read Config from:', configPath)
      const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'))
      if(config.captionWindowWidth) this.captionWindowWidth = config.captionWindowWidth
      if(config.uiLanguage) this.uiLanguage = config.uiLanguage
      if(config.uiTheme) this.uiTheme = config.uiTheme
      if(config.uiColor) this.uiColor = config.uiColor
      if(config.leftBarWidth) this.leftBarWidth = config.leftBarWidth
      if(config.styles) this.setStyles(config.styles)
      if(config.controls) this.setControls(config.controls)
    }
  }

  public writeConfig() {
    const config = {
      captionWindowWidth: this.captionWindowWidth,
      uiLanguage: this.uiLanguage,
      uiTheme: this.uiTheme,
      uiColor: this.uiColor,
      leftBarWidth: this.leftBarWidth,
      controls: this.controls,
      styles: this.styles
    }
    const configPath = path.join(app.getPath('userData'), 'config.json')
    fs.writeFileSync(configPath, JSON.stringify(config, null, 2))
    Log.info('Write Config to:', configPath)
  }

  public getFullConfig(softwareLog: SoftwareLogItem[]): FullConfig {
    return {
      platform: process.platform,
      uiLanguage: this.uiLanguage,
      uiTheme: this.uiTheme,
      uiColor: this.uiColor,
      leftBarWidth: this.leftBarWidth,
      styles: this.styles,
      controls: this.controls,
      captionLog: this.captionLog,
      softwareLog: softwareLog
    }
  }

  public setStyles(args: Object) {
    for(let key in this.styles) {
      if(key in args) {
        this.styles[key] = args[key]
      }
    }
    Log.info('Set Styles:', this.styles)
  }

  public resetStyles() {
    this.setStyles(defaultStyles)
  }

  public sendStyles(window: BrowserWindow) {
    window.webContents.send('both.styles.set', this.styles)
    Log.info(`Send Styles to #${window.id}:`, this.styles)
  }

  public setControls(args: Object) {
    const engineEnabled = this.controls.engineEnabled
    for(let key in this.controls){
      if(key in args) {
        this.controls[key] = args[key]
      }
    }
    this.controls.engineEnabled = engineEnabled
    Log.info('Set Controls:', passwordMaskingForObject(this.controls))
  }

  public sendControls(window: BrowserWindow, info = true) {
    window.webContents.send('control.controls.set', this.controls)
    if(info) Log.info(`Send Controls to #${window.id}:`, this.controls)
  }

  public updateCaptionLog(log: CaptionItem) {
    let command: 'add' | 'upd' = 'add'
    if(
      this.captionLog.length &&
      this.lastLogIndex === log.index
    ) {
      this.captionLog.splice(this.captionLog.length - 1, 1, log)
      command = 'upd'
    }
    else {
      this.captionLog.push(log)
      this.lastLogIndex = log.index
    }
    this.captionLog[this.captionLog.length - 1].index = this.captionLog.length
    for(const window of BrowserWindow.getAllWindows()){
      this.sendCaptionLog(window, command)
    }
  }

  public updateCaptionTranslation(trans: CaptionTranslation){
    for(let i = this.captionLog.length - 1; i >= 0; i--){
      if(this.captionLog[i].time_s === trans.time_s){
        this.captionLog[i].translation = trans.translation
        for(const window of BrowserWindow.getAllWindows()){
          this.sendCaptionLog(window, 'upd', i)
        }
        break
      }
    }
  }
  public sendCaptionLog(
    window: BrowserWindow,
    command: 'add' | 'upd' | 'set',
    index: number | undefined = undefined
  ) {
    if(command === 'add'){
      window.webContents.send(`both.captionLog.add`, this.captionLog.at(-1))
    }
    else if(command === 'upd'){
      if(index !== undefined) window.webContents.send(`both.captionLog.upd`, this.captionLog[index])
      else window.webContents.send(`both.captionLog.upd`, this.captionLog.at(-1))
    }
    else if(command === 'set'){
      window.webContents.send(`both.captionLog.set`, this.captionLog)
    }
  }
}

export const allConfig = new AllConfig()
