// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:ffi';
import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:ffi/ffi.dart';
import 'package:ffigen/src/code_generator.dart';
import 'package:ffigen/src/header_parser/data.dart';
import 'package:ffigen/src/header_parser/includer.dart';
import 'package:logging/logging.dart';

import '../clang_bindings/clang_bindings.dart' as clang_types;
import '../data.dart';
import '../utils.dart';

var _logger = Logger('ffigen.header_parser.macro_parser');

/// Saved macros, Key: prefixedName, Value originalName.
final _savedMacros = <String, String>{};

/// Adds a macro definition to be parsed later.
void saveMacroDefinition(Pointer<clang_types.CXCursor> cursor) {
  final originalMacroName = cursor.spelling();
  if (shouldIncludeMacro(originalMacroName) &&
      !isSeenMacro(originalMacroName) &&
      clang.clang_Cursor_isMacroBuiltin_wrap(cursor) == 0 &&
      clang.clang_Cursor_isMacroFunctionLike_wrap(cursor) == 0) {
    // Parse macro only if it's not builtin or function-like.
    _logger.fine(
        "++++ Saved Macro '$originalMacroName' for later : ${cursor.completeStringRepr()}");
    final prefixedName = config.macroDecl.getPrefixedName(originalMacroName);
    addMacroToSeen(originalMacroName, prefixedName);
    _saveMacro(prefixedName, originalMacroName);
  }
}

/// Saves a macro to be parsed later.
///
/// Macros are parsed later in [parseSavedMacros()].
void _saveMacro(String name, String originalName) {
  _savedMacros[name] = originalName;
}

List<Constant> _bindings;

/// Macros cannot be parsed directly, so we create a new `.hpp` file in which
/// they are assigned to a variable after which their value can be determined
/// by evaluating the value of the variable.
List<Constant> parseSavedMacros() {
  _bindings = [];

  if (_savedMacros.keys.isEmpty) {
    return _bindings;
  }

  // Create a file for parsing macros;
  final file = createFileForMacros();

  final index = clang.clang_createIndex(0, 0);
  Pointer<Pointer<Utf8>> clangCmdArgs = nullptr;
  var cmdLen = 0;
  if (config.compilerOpts != null) {
    clangCmdArgs = createDynamicStringArray(config.compilerOpts);
    cmdLen = config.compilerOpts.length;
  }
  final tu = clang.clang_parseTranslationUnit(
    index,
    Utf8.toUtf8(file.path).cast(),
    clangCmdArgs.cast(),
    cmdLen,
    nullptr,
    0,
    clang_types.CXTranslationUnit_Flags.CXTranslationUnit_KeepGoing,
  );

  if (tu == nullptr) {
    _logger.severe('Unable to parse Macros.');
  } else {
    final rootCursor = clang.clang_getTranslationUnitCursor_wrap(tu);

    final resultCode = clang.clang_visitChildren_wrap(
      rootCursor,
      Pointer.fromFunction(_macroVariablevisitor,
          clang_types.CXChildVisitResult.CXChildVisit_Break),
      uid,
    );

    visitChildrenResultChecker(resultCode);
    rootCursor.dispose();
  }

  clang.clang_disposeTranslationUnit(tu);
  clang.clang_disposeIndex(index);
  // Delete the temp file created for macros.
  file.deleteSync();

  return _bindings;
}

/// Child visitor invoked on translationUnitCursor for parsing macroVariables.
int _macroVariablevisitor(Pointer<clang_types.CXCursor> cursor,
    Pointer<clang_types.CXCursor> parent, Pointer<Void> clientData) {
  Constant constant;
  try {
    if (isFromGeneratedFile(cursor) &&
        _macroVarNames.contains(cursor.spelling()) &&
        cursor.kind() == clang_types.CXCursorKind.CXCursor_VarDecl) {
      final e = clang.clang_Cursor_Evaluate_wrap(cursor);
      final k = clang.clang_EvalResult_getKind(e);
      _logger.fine('macroVariablevisitor: ${cursor.completeStringRepr()}');

      /// Get macro name, the variable name starts with '<macro-name>_'.
      final macroName = MacroVariableString.decode(cursor.spelling());
      switch (k) {
        case clang_types.CXEvalResultKind.CXEval_Int:
          constant = Constant(
            originalName: _savedMacros[macroName],
            name: macroName,
            rawType: 'int',
            rawValue: clang.clang_EvalResult_getAsLongLong(e).toString(),
          );
          break;
        case clang_types.CXEvalResultKind.CXEval_Float:
          constant = Constant(
            originalName: _savedMacros[macroName],
            name: macroName,
            rawType: 'double',
            rawValue: clang.clang_EvalResult_getAsDouble(e).toString(),
          );
          break;
        case clang_types.CXEvalResultKind.CXEval_StrLiteral:
          constant = Constant(
            originalName: _savedMacros[macroName],
            name: macroName,
            rawType: 'String',
            rawValue:
                "'${Utf8.fromUtf8(clang.clang_EvalResult_getAsStr(e).cast())}'",
          );
          break;
      }
      clang.clang_EvalResult_dispose(e);

      if (constant != null) {
        _bindings.add(constant);
      }
    }
    cursor.dispose();
    parent.dispose();
  } catch (e, s) {
    _logger.severe(e);
    _logger.severe(s);
    rethrow;
  }
  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
}

/// Returns true if cursor is from generated file.
bool isFromGeneratedFile(Pointer<clang_types.CXCursor> cursor) {
  final s = cursor.sourceFileName();
  if (s == null || s.isEmpty) {
    return false;
  } else {
    return p.basename(s) == _generatedFileBaseName;
  }
}

/// Base name of generated file.
String _generatedFileBaseName;

/// Generated macro variable names.
///
/// Used to determine if macro should be included in bindings or not.
Set<String> _macroVarNames = {};

/// Creates a temporary file for parsing macros in current directory.
File createFileForMacros() {
  final fileNameBase = 'temp_for_macros';
  final fileExt = 'hpp';

  // Find a filename which doesn't already exist.
  var file = File('$fileNameBase.$fileExt');
  var i = 0;
  while (file.existsSync()) {
    i++;
    file = File('${fileNameBase.split('.')[0]}_$i.$fileExt');
  }

  // Create file.
  file.createSync();
  // Save generted name.
  _generatedFileBaseName = p.basename(file.path);

  // Write file contents.
  final sb = StringBuffer();
  for (final h in config.headers.entryPoints) {
    sb.writeln('#include "$h"');
  }

  _macroVarNames = {};
  for (final prefixedMacroName in _savedMacros.keys) {
    // Write macro.
    final macroVarName = MacroVariableString.encode(prefixedMacroName);
    sb.writeln('auto ${macroVarName} = ${_savedMacros[prefixedMacroName]};');
    // Add to _macroVarNames.
    _macroVarNames.add(macroVarName);
  }
  final macroFileContent = sb.toString();
  // Log this generated file for debugging purpose.
  // We use the finest log because this file may be very big.
  _logger.finest('=====FILE FOR MACROS====');
  _logger.finest(macroFileContent);
  _logger.finest('========================');

  file.writeAsStringSync(macroFileContent);
  return file;
}

/// Deals with encoding/decoding name of the variable generated for a Macro.
class MacroVariableString {
  static String encode(String s) {
    return '_${s.length}_${s}_generated_macro_variable';
  }

  static String decode(String s) {
    // Remove underscore.
    s = s.substring(1);
    final intReg = RegExp('[0-9]+');
    final lengthEnd = intReg.matchAsPrefix(s).end;
    final len = int.parse(s.substring(0, lengthEnd));

    // Name starts after an unerscore.
    final nameStart = lengthEnd + 1;
    return s.substring(nameStart, nameStart + len);
  }
}
