/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as vscode from 'vscode'
import * as fs from 'fs'
import * as os from 'os'
import * as child_process from 'child_process'
import path from 'path'
import { VSCodeLaunchConfigArgs } from './classes/vscode-launch'
import { InfosetOutput } from './daffodilDebugger'
import { XMLParser } from 'fast-xml-parser'
import * as unzip from 'unzip-stream'
import { pipeline } from 'stream/promises'
import { Transform } from 'stream'
let currentConfig: vscode.DebugConfiguration

export const terminalName = 'daffodil-debugger'

export const regexp = {
  comma: new RegExp(',', 'g'),
  slash: new RegExp('/', 'g'),
  space: new RegExp(' ', 'g'),
  workspace: new RegExp('${workspaceFolder}', 'g'),
}

// Function to retrieve to the current debug config
export function getCurrentConfig(): vscode.DebugConfiguration {
  return currentConfig
}

// Function to set the current debug config
export function setCurrentConfig(
  config: vscode.DebugConfiguration
): vscode.DebugConfiguration {
  currentConfig = config
  return config
}

// Function to run vscode command and catch the error to not cause other issues
export function runCommand(command: string, params?: any) {
  const vscodeError = (err) => {
    vscode.window.showInformationMessage(err)
  }

  if (!params)
    vscode.commands.executeCommand(command).then(undefined, vscodeError)
  else
    vscode.commands.executeCommand(command, params).then(undefined, vscodeError)
}

// Function for checking if config specifies if either the
// infoset, infoset diff or data editor needs to be opened
export async function onDebugStartDisplay(viewsToCheck: string[]) {
  let config = getCurrentConfig()

  viewsToCheck.forEach(async (viewToCheck) => {
    switch (viewToCheck) {
      case 'data-editor':
        if (config.openDataEditor) {
          runCommand('extension.data.edit', config.data)
        }
        break
      case 'infoset-view':
        if (config.openInfosetView) {
          runCommand('infoset.display')
        }
        break
      case 'infoset-diff-view':
        if (config.openInfosetDiffView) {
          runCommand('infoset.diff')
        }
        break
    }
  })
}

function checkInfosetFileExtension(
  infosetOutput: InfosetOutput,
  infosetFormat: string
) {
  // If the infoset file path doesn't end with the infoset output format, update to end with infoset output format.
  if (!infosetOutput.path.endsWith(`.${infosetFormat}`)) {
    vscode.window.showWarningMessage(
      `The output path for the file extension doesn't end with the infoset output format type. The file extension will be updated to end with .${infosetFormat}`
    )

    let fileExtensionSearchResult = new RegExp('(\\.).*$')
      .exec(infosetOutput!.path)
      ?.filter((fileExt) => fileExt !== '.')[0]

    /**
     * If search result is not undefined replace the file extension with the correct extension.
     * Else append proper file extension to the end of the output path.
     */
    infosetOutput.path =
      fileExtensionSearchResult !== undefined
        ? infosetOutput.path.replace(
            fileExtensionSearchResult,
            `.${infosetFormat}`
          )
        : (infosetOutput.path = `${infosetOutput!.path}.${infosetFormat}`)
  }
}

function checkSettingValue<T>(target: unknown, defaults: T): T {
  if (
    typeof defaults !== 'object' ||
    defaults === null ||
    Array.isArray(defaults)
  ) {
    return target === undefined ? defaults : (target as T)
  }

  if (typeof target !== 'object' || target === null) {
    return defaults
  }

  const result: Record<string, any> = {}

  for (const key of Object.keys(defaults)) {
    result[key] = checkSettingValue(
      (target as any)[key],
      (defaults as any)[key]
    )
  }

  for (const key of Object.keys(target as any)) {
    if (!(key in result)) {
      result[key] = (target as any)[key]
    }
  }

  return result as T
}

export function getConfig(jsonArgs: object): vscode.DebugConfiguration {
  const launchConfigArgs: VSCodeLaunchConfigArgs = JSON.parse(
    JSON.stringify(jsonArgs)
  )
  // NOTE: Don't make this a static value as extension configuration may change while the extension is loaded.
  const defaultConf = vscode.workspace.getConfiguration()

  const defaultValues = {
    schema: defaultConf.get('schema', {
      path: '${command:AskForSchemaName}',
      rootName: null,
      rootNamespace: null,
    }),
    data: defaultConf.get('data', '${command:AskForDataName}'),
    debugServer: defaultConf.get('debugServer', 4711),
    infosetFormat: 'xml',
    infosetOutput: defaultConf.get('infosetOutput', {
      type: 'file',
      path: '${workspaceFolder}/target/infoset.xml',
    }),
    tdmlConfig: {
      ...{
        action: 'generate',
        name: 'Default Test Case',
        path: '${command:AskForValidatedTDMLPath}',
      },
      ...((defaultConf.get('tdmlConfig') as object) || {}),
    },
    stopOnEntry: defaultConf.get('stopOnEntry', true),
    useExistingServer: defaultConf.get('useExistingServer', false),
    trace: defaultConf.get('trace', true),
    openDataEditor: defaultConf.get('openDataEditor', false),
    openInfosetView: defaultConf.get('openInfosetView', false),
    openInfosetDiffView: defaultConf.get('openInfosetDiffView', false),
    daffodilDebugClasspath: defaultConf.get('daffodilDebugClasspath', []),
    dataEditor: defaultConf.get('dataEditor', {
      port: 9000,
      logging: {
        level: 'info',
        file: '',
      },
    }),
    dfdlDebugger: defaultConf.get('dfdlDebugger', {
      daffodilVersion: '3.11.0',
      timeout: '10s',
      logging: {
        level: 'INFO',
        file: '${workspaceFolder}/daffodil-debugger.log',
      },
    }),
  }

  for (const [key, defaults] of Object.entries(defaultValues)) {
    launchConfigArgs[key] = checkSettingValue(launchConfigArgs[key], defaults)
  }

  if (launchConfigArgs.infosetOutput?.type == 'file') {
    checkInfosetFileExtension(
      launchConfigArgs.infosetOutput!,
      launchConfigArgs.infosetFormat!
    )
  }

  // VVVVVVVVVVVVVVVVVVVVVVVV COMPARTMENTALIZED FIX FOR THIRD BULLET POINT OF https://github.com/apache/daffodil-vscode/issues/1540 VVVVVVVVVVVVVVVVVVVVVVVV
  // Handle setting test case name for TDML Execute action if it's not specified.
  // This resolves the issue of always defualting to `Default Test Case` even thought a test case name isn't specified when we click on `Execute TDML` when we have opened TDML file
  const args = jsonArgs as VSCodeLaunchConfigArgs // cast needed b/c of VS Code Typescript errors
  if (
    args.tdmlConfig?.action === 'execute' &&
    args.tdmlConfig?.name === undefined
  ) {
    launchConfigArgs.tdmlConfig.name = undefined
  }
  // ^^^^^^^^^^^^^^^^^^^^^^^^ COMPARTMENTALIZED FIX FOR THIRD BULLET POINT OF https://github.com/apache/daffodil-vscode/issues/1540 ^^^^^^^^^^^^^^^^^^^^^^^^

  return JSON.parse(JSON.stringify(launchConfigArgs))
}

export async function displayTerminalExitStatus(terminal: vscode.Terminal) {
  vscode.window.onDidCloseTerminal((t) => {
    if (t.name === terminal.name && t.processId === terminal.processId) {
      t.show()
      vscode.window.showInformationMessage(
        `Terminal exited with status code: ${t.exitStatus?.code}`
      )
    }
  })
}

/*
 * Check if OS is windows, if so return windows option else return the mac and linux option.
 * This method is used to elimate a lot duplicated code we had check if the os was windows related.
 */
export function osCheck(winOption: any, macLinOption: any): any {
  return os.platform().toLowerCase().startsWith('win')
    ? winOption
    : macLinOption
}

export async function killProcess(id: number | undefined) {
  if (id) {
    child_process.exec(
      osCheck(`taskkill /F /PID ${id}`, `kill -9 ${id} 2>&1 || echo 0`)
    )
  }
}

export const delay = (ms: number) => new Promise((res) => setTimeout(res, ms))

// Grab active terminal if available and it can run a new command, else create new one
export const getTerminal = (
  hideTerminal: boolean,
  env:
    | {
        [key: string]: string | null | undefined
      }
    | undefined,
  createTerminal: boolean
) => {
  if (!createTerminal) {
    vscode.window.terminals.forEach((terminal) => {
      if (terminal.name.includes(terminalName)) terminal.dispose()
    })
  }

  // If no good active terminal available create new one
  const terminal = vscode.window.createTerminal({
    name: terminalName,
    hideFromUser: hideTerminal,
    // Need to specify 'cmd' for windows as by default it will use powershell which causes issues with the envionment varaibles
    shellPath: osCheck('cmd', undefined),
  })

  // Looping to manual set all env variables. Setting "env: env" inside of createTerminal won't override variables already set
  for (var key in env) {
    if (key !== null && key !== undefined) {
      let workspaceFolder = vscode.workspace.workspaceFolders
        ? vscode.workspace.workspaceFolders[0].uri.fsPath
        : ''

      /*
       * NOTE: For windows to function properly the set format needs to be:
       *         set "VARIABLE_NAME=VARIABLE_VALUE"
       * In bash doing:
       *         export "VARIABLE_NAME=VARIABLE_VALUE"
       * didn't cause any issues so this was easiest work around.
       */
      let exportVar = `${osCheck('set', 'export')} "${key}=${env[key]}"`

      if (exportVar.includes('${workspaceFolder}')) {
        exportVar = exportVar.replaceAll('${workspaceFolder}', workspaceFolder)
      }

      terminal.sendText(exportVar, true)
    }
  }

  return terminal
}

export async function runScript(
  scriptPath: string,
  scriptName: string,
  createTerminal: boolean,
  shellArgs: string[] = [],
  env:
    | {
        [key: string]: string | null | undefined
      }
    | undefined = undefined,
  type: string = '',
  hideTerminal: boolean = false,
  port: number | undefined = undefined
): Promise<vscode.Terminal> {
  // Get the full path to the script
  const scriptFullPath = path.join(scriptPath, 'bin', scriptName)

  // Make sure the path exists
  if (!fs.existsSync(scriptFullPath)) {
    vscode.window.showErrorMessage(
      `Script path ${scriptFullPath} does not exist`
    )
  } else {
    // Make sure the script is executable
    if (!os.platform().toLowerCase().startsWith('win')) {
      fs.chmodSync(scriptFullPath, 0o755)
    }
  }

  const terminal = getTerminal(hideTerminal, env, createTerminal)

  // Create debugger run command
  const fullPathToScript = path
    .join(scriptPath, 'bin', scriptName)
    // fix pathing as emtpy space needs a \ before it to not cause errors
    .replace(' ', '\\ ')
  const debuggerRunCommand = `${fullPathToScript} ${shellArgs.join(' ')}`

  // Send debugger run command to terminal, when exists terminal will stay open
  terminal.sendText(debuggerRunCommand)

  if (!hideTerminal) {
    terminal.show()
    await displayTerminalExitStatus(terminal)
  }

  if (type.includes('daffodil')) {
    await delay(5000).then(() => {})
  } else {
    const wait_port = require('wait-port')
    await wait_port({ host: '127.0.0.1', port: port, output: 'silent' })
  }

  return terminal
}

/**
 * Search for an existing Omega Edit server and kill if desired.
 * @param killOnFind Kill any OmegaEdit server found that is running. Defaults to True.
 * @returns PID of the process found and/or killed. 0 if no server is found. -1 if a child_process error occurred.
 */
export async function findExistingOmegaEditServer(
  killOnFind: boolean = true
): Promise<number> {
  let ret: number
  const pid: string = child_process
    .execSync(
      osCheck('', "ps -a | grep omega-edit | grep -v grep | awk '{print $1}'")
    )
    .toString('ascii')

  pid === '' ? (ret = 0) : (ret = parseInt(pid))

  if (ret > 0 && killOnFind) {
    vscode.window.showWarningMessage(
      `Existing Omega Edit server found | Killing PID: ${ret} and restarting server.`
    )
    await killProcess(ret)
  }
  return ret
}

export function tmpFile(sid: string): string {
  return `${os.tmpdir()}/infoset-${sid}.${getCurrentConfig().infosetFormat}`
}

export function ensureFile(path: string): string {
  if (!fs.existsSync(path)) {
    fs.writeFileSync(path, '')
  }
  return path
}

/**
 * Substitutes in VSCode and environmental variables into a given string.
 *
 * @param input - given string
 * @param alternativeWorkspace - alternative workspace location if vscode can't find a good workspace
 * @returns modified input, but with all ${} corresponding to VSCode or Env variables substituted with their
 */
export function substituteVSCodeEnvVariables(
  input: string,
  alternativeWorkspace?: string
): string {
  const workspaceFolder =
    vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ||
    alternativeWorkspace ||
    ''
  const homeDir = os.homedir()

  // Common VS Code variables
  const variableMap: Record<string, string> = {
    '${workspaceFolder}': workspaceFolder,
    '${workspaceRoot}': workspaceFolder,
    '${userHome}': homeDir,
    '${file}': vscode.window.activeTextEditor?.document.uri.fsPath || '',
    '${relativeFile}': path.relative(
      workspaceFolder,
      vscode.window.activeTextEditor?.document.uri.fsPath || ''
    ),
    '${fileBasename}': path.basename(
      vscode.window.activeTextEditor?.document.uri.fsPath || ''
    ),
    '${fileDirname}': path.dirname(
      vscode.window.activeTextEditor?.document.uri.fsPath || ''
    ),
    '${fileExtname}': path.extname(
      vscode.window.activeTextEditor?.document.uri.fsPath || ''
    ),
    '${fileBasenameNoExtension}': path.basename(
      vscode.window.activeTextEditor?.document.uri.fsPath || '',
      path.extname(vscode.window.activeTextEditor?.document.uri.fsPath || '')
    ),
    '${cwd}': process.cwd(),
  }

  // Add all environment variables dynamically
  Object.entries(process.env).forEach(([key, value]) => {
    if (value) {
      variableMap[`$\{env:${key}\}`] = value
    }
  })

  // Substitute all variables in the input string
  return Object.entries(variableMap).reduce((result, [variable, value]) => {
    return result.replaceAll(variable, value)
  }, input)
}

/**
 * Retrieves an array of test case items from a TDML (Test Data Markup Language) file.
 *
 * @param path - The file path to the TDML file.
 * @returns An array of test case names
 */
export function getTDMLTestCaseItems(path: string): string[] {
  if (!fs.existsSync(path)) {
    return [] // TDML file not found
  }

  // Needed objects for parsing
  const parser = new XMLParser({
    ignoreAttributes: false,
    removeNSPrefix: true,
  })
  const fileData = fs.readFileSync(path)

  // representaiton of TDML XML file as JS object
  const xml_obj = parser.parse(fileData)

  // Read through TDML test cases and populate each TDML test case item if XML file is valid enough
  // parserTestCaseObjs can be either an array of objects, a single object, or undefined if no parserTestCase element was found
  // Convert that into an array and return a list containing the names of each parserTestCase element
  const parserTestCaseObjs = xml_obj['testSuite']?.['parserTestCase']
  const testCaseArr = Array.isArray(parserTestCaseObjs)
    ? parserTestCaseObjs
    : parserTestCaseObjs
      ? [parserTestCaseObjs]
      : []
  return testCaseArr.map((item) => item['@_name'])
}

/**
 * Displays a VSCode error message as modal. In some cases such as when running tests, using modal
 * can cause an error because the dialog service is not available. If this happens when trying
 * to display the message, this error is grabbed and then message is displayed with modal disabled.
 *
 * @param message - The message to display
 * @param items — A set of items that will be rendered as actions in the message.
 * @returns — A thenable that resolves to the selected item or undefined when being dismissed.
 */
export const displayModalError = async (
  message: string,
  ...items: string[]
): Promise<Thenable<string | undefined>> =>
  vscode.window
    .showErrorMessage(message, { modal: true }, ...items)
    .then(undefined, () =>
      vscode.window.showErrorMessage(message, { modal: false })
    )

/**
 * Make HTTP request with retries and exponential backoff
 *
 * @param url The url to fetch
 * @param options The options for the fetch
 * @param retries Max number of retries
 * @param delay Initial delay in ms
 * @returns Response object
 */
export async function fetchRetry(
  url,
  options = {},
  retries = 5,
  delay = 4000
): Promise<Response | undefined> {
  let backoff = delay
  for (let i = 1; i <= retries; i++) {
    const res = await fetch(url, options)
    if (!res.ok || !res.body) {
      if (i === retries) {
        throw new Error(
          `Failed request to ${url}: ${res.status} ${res.statusText}`
        )
      } else {
        await new Promise((r) => setTimeout(r, backoff))
        backoff = backoff * 2
      }
    } else {
      return res
    }
  }
}

/**
 * Download and extract a files with a progress bar
 *
 * @param title A title to use for printing to the user what is being downloaded
 * @param url The url to donwload the binary from
 * @param targetDir The directory to target for extraction
 */
export async function downloadAndExtract(
  title: string,
  url: string,
  targetDir: string
): Promise<void> {
  await vscode.window.withProgress(
    {
      location: vscode.ProgressLocation.Notification,
      title: `Downloading ${title}...`,
      cancellable: false,
    },
    async (progress) => {
      progress.report({ increment: 0, message: 'Starting download...' })

      const res = await fetchRetry(url)
      if (!res) {
        throw new Error(`Failed to download ${url}`)
      }

      const totalBytes = Number(res.headers.get('content-length')) || 0
      let downloaded = 0
      let lastPercent = 0

      // Transform stream to track download progress
      const progressStream = new Transform({
        transform(chunk: Buffer, _encoding, callback) {
          downloaded += chunk.length
          if (totalBytes > 0) {
            const percent = (downloaded / totalBytes) * 100
            const increment = percent - lastPercent
            lastPercent = percent
            progress.report({
              increment,
              message: `${percent.toFixed(1)}%`,
            })
          }
          callback(null, chunk)
        },
      })

      await fs.promises.mkdir(targetDir, { recursive: true })

      await pipeline(
        res.body as any,
        progressStream,
        unzip.Extract({ path: targetDir })
      )

      progress.report({
        increment: 100 - lastPercent,
        message: 'Extracting complete!',
      })
    }
  )
}
