// 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 'package:ffigen/src/code_generator/utils.dart';
import 'package:meta/meta.dart';

import 'binding.dart';
import 'typedef.dart';

/// To store generated String bindings.
class Writer {
  final String header;

  /// Holds bindings, which lookup symbols.
  final List<Binding> lookUpBindings;

  /// Holds bindings which don't lookup symbols.
  final List<Binding> noLookUpBindings;

  String _className;
  final String classDocComment;

  String _ffiLibraryPrefix;
  String get ffiLibraryPrefix => _ffiLibraryPrefix;

  String _dylibIdentifier;
  String get dylibIdentifier => _dylibIdentifier;

  /// Initial namers set after running constructor. Namers are reset to this
  /// initial state everytime [generate] is called.
  UniqueNamer _initialTopLevelUniqueNamer, _initialWrapperLevelUniqueNamer;

  /// Used by [Binding]s for generating required code.
  UniqueNamer _topLevelUniqueNamer, _wrapperLevelUniqueNamer;
  UniqueNamer get topLevelUniqueNamer => _topLevelUniqueNamer;
  UniqueNamer get wrapperLevelUniqueNamer => _wrapperLevelUniqueNamer;

  String _arrayHelperClassPrefix;

  /// Guaranteed to be a unique prefix.
  String get arrayHelperClassPrefix => _arrayHelperClassPrefix;

  /// [_usedUpNames] should contain names of all the declarations which are
  /// already used. This is used to avoid name collisions.
  Writer({
    @required this.lookUpBindings,
    @required this.noLookUpBindings,
    @required String className,
    this.classDocComment,
    this.header,
  }) : assert(className != null) {
    final globalLevelNameSet = noLookUpBindings.map((e) => e.name).toSet();
    final wrapperLevelNameSet = lookUpBindings.map((e) => e.name).toSet();
    final allNameSet = <String>{}
      ..addAll(globalLevelNameSet)
      ..addAll(wrapperLevelNameSet);

    _initialTopLevelUniqueNamer = UniqueNamer(globalLevelNameSet);
    _initialWrapperLevelUniqueNamer = UniqueNamer(wrapperLevelNameSet);
    final allLevelsUniqueNamer = UniqueNamer(allNameSet);

    /// Wrapper class name must be unique among all names.
    _className = allLevelsUniqueNamer.makeUnique(className);
    _initialWrapperLevelUniqueNamer.markUsed(_className);
    _initialTopLevelUniqueNamer.markUsed(_className);

    /// [_ffiLibraryPrefix] should be unique in top level.
    _ffiLibraryPrefix = _initialTopLevelUniqueNamer.makeUnique('ffi');

    /// [_dylibIdentifier] should be unique in top level.
    _dylibIdentifier = _initialTopLevelUniqueNamer.makeUnique('_dylib');

    /// Finding a unique prefix for Array Helper Classes and store into
    /// [_arrayHelperClassPrefix].
    final base = 'ArrayHelper';
    _arrayHelperClassPrefix = base;
    var suffixInt = 0;
    for (var i = 0; i < allNameSet.length; i++) {
      if (allNameSet.elementAt(i).startsWith(_arrayHelperClassPrefix)) {
        // Not a unique prefix, start over with a new suffix.
        i = -1;
        suffixInt++;
        _arrayHelperClassPrefix = '${base}${suffixInt}';
      }
    }

    _resetUniqueNamersNamers();
  }

  /// Resets the namers to initial state. Namers are reset before generating.
  void _resetUniqueNamersNamers() {
    _topLevelUniqueNamer = _initialTopLevelUniqueNamer.clone();
    _wrapperLevelUniqueNamer = _initialWrapperLevelUniqueNamer.clone();
  }

  /// Writes all bindings to a String.
  String generate() {
    final s = StringBuffer();

    // Reset unique namers to initial state.
    _resetUniqueNamersNamers();

    // Write file header (if any).
    if (header != null) {
      s.write(header);
      s.write('\n');
    }

    // Write auto generated declaration.
    s.write(makeDoc(
        'AUTO GENERATED FILE, DO NOT EDIT.\n\nGenerated by `package:ffigen`.'));

    // Write neccesary imports.
    s.write("import 'dart:ffi' as $ffiLibraryPrefix;\n");
    s.write('\n');

    // Will contain duplicates, must be processed.
    final rawDependencies = <Typedef>[];

    /// Get typedef dependencies, these will be written at the end.
    for (final b in lookUpBindings) {
      rawDependencies.addAll(b.getTypedefDependencies(this));
    }
    for (final b in noLookUpBindings) {
      rawDependencies.addAll(b.getTypedefDependencies(this));
    }

    // Dependencies, processed to remove duplicates and resolve name conflicts.
    final dependencies = processDependencies(rawDependencies);

    /// Write [lookUpBindings].
    if (lookUpBindings.isNotEmpty) {
      // Write doc comment for wrapper class.
      if (classDocComment != null) {
        s.write(makeDartDoc(classDocComment));
      }
      // Write wrapper classs.
      s.write('class $_className{\n');
      // Write dylib.
      s.write('/// Holds the Dynamic library.\n');
      s.write('final $ffiLibraryPrefix.DynamicLibrary ${dylibIdentifier};\n');
      s.write('\n');
      //Write doc comment for wrapper class constructor.
      s.write(makeDartDoc('The symbols are looked up in [dynamicLibrary].'));
      // Write wrapper class constructor.
      s.write(
          '${_className}($ffiLibraryPrefix.DynamicLibrary dynamicLibrary): $dylibIdentifier = dynamicLibrary;\n\n');
      for (final b in lookUpBindings) {
        s.write(b.toBindingString(this).string);
      }
      s.write('}\n\n');
    }

    /// Write [noLookUpBindings].
    for (final b in noLookUpBindings) {
      s.write(b.toBindingString(this).string);
    }

    // Write typedef dependencies.
    for (final d in dependencies) {
      s.write(d.toTypedefString(this));
    }

    return s.toString();
  }

  /// Removes duplicates and resolves all name conflicts.
  Set<Typedef> processDependencies(List<Typedef> dependencies) {
    final processedDependencies = dependencies.toSet();

    for (final d in processedDependencies) {
      d.name = _makeUniqueTypedefName(d.name);
    }
    return processedDependencies;
  }

  /// Returns a typedef name that is unique in both top level and wrapper level,
  /// ans only marks it as used at top-level.
  String _makeUniqueTypedefName(String name) {
    final base = name;
    var uniqueName = name;
    var suffix = 0;
    while (topLevelUniqueNamer.isUsed(uniqueName) ||
        wrapperLevelUniqueNamer.isUsed(uniqueName)) {
      suffix++;
      uniqueName = base + suffix.toString();
    }
    topLevelUniqueNamer.markUsed(uniqueName);
    return uniqueName;
  }
}
