// Copyright (c) 2014, 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.

/**
 * Tools for code generation.
 */
library codegen.tools;

import 'dart:io';

import 'package:html5lib/dom.dart' as dom;
import 'package:path/path.dart';

import 'text_formatter.dart';
import 'html_tools.dart';

/**
 * Join the given strings using camelCase.  If [doCapitalize] is true, the first
 * part will be capitalized as well.
 */
String camelJoin(List<String> parts, {bool doCapitalize: false}) {
  List<String> upcasedParts = <String>[];
  for (int i = 0; i < parts.length; i++) {
    if (i == 0 && !doCapitalize) {
      upcasedParts.add(parts[i]);
    } else {
      upcasedParts.add(capitalize(parts[i]));
    }
  }
  return upcasedParts.join();
}

/**
 * Capitalize and return the passed String.
 */
String capitalize(String string) {
  return string[0].toUpperCase() + string.substring(1);
}

final RegExp trailingWhitespaceRegExp = new RegExp(r' +$', multiLine: true);

/**
 * Mixin class for generating code.
 */
class CodeGenerator {
  _CodeGeneratorState _state;

  /**
   * Execute [callback], collecting any code that is output using [write]
   * or [writeln], and return the result as a string.
   */
  String collectCode(void callback()) {
    _CodeGeneratorState oldState = _state;
    try {
      _state = new _CodeGeneratorState();
      callback();
      return _state.buffer.toString().replaceAll(trailingWhitespaceRegExp, '');
    } finally {
      _state = oldState;
    }
  }

  /**
   * Output text without ending the current line.
   */
  void write(Object obj) {
    _state.write(obj.toString());
  }

  /**
   * Output text, ending the current line.
   */
  void writeln([Object obj = '']) {
    _state.write('$obj\n');
  }

  /**
   * Execute [callback], indenting any code it outputs by two spaces.
   */
  void indent(void callback()) => indentSpecial('  ', '  ', callback);

  /**
   * Execute [callback], using [additionalIndent] to indent any code it outputs.
   */
  void indentBy(String additionalIndent, void callback()) =>
      indentSpecial(additionalIndent, additionalIndent, callback);

  /**
   * Execute [callback], using [additionalIndent] to indent any code it outputs.
   * The first line of output is indented by [firstAdditionalIndent] instead of
   * [additionalIndent].
   */
  void indentSpecial(String firstAdditionalIndent, String additionalIndent, void
      callback()) {
    String oldNextIndent = _state.nextIndent;
    String oldIndent = _state.indent;
    try {
      _state.nextIndent += firstAdditionalIndent;
      _state.indent += additionalIndent;
      callback();
    } finally {
      _state.nextIndent = oldNextIndent;
      _state.indent = oldIndent;
    }
  }

  /**
   * Measure the width of the current indentation level.
   */
  int get indentWidth => _state.nextIndent.length;

  /**
   * Generate a doc comment based on the HTML in [docs].
   *
   * If [javadocStyle] is true, then the output is compatable with Javadoc,
   * which understands certain HTML constructs.
   */
  void docComment(List<dom.Node> docs, {int width: 79, bool javadocStyle:
      false}) {
    if (containsOnlyWhitespace(docs)) {
      return;
    }
    writeln('/**');
    indentBy(' * ', () {
      write(nodesToText(docs, width - _state.indent.length, javadocStyle));
    });
    writeln(' */');
  }

  void outputHeader({bool javaStyle: false}) {
    String header;
    if (javaStyle) {
      header = '''
/*
 * Copyright (c) 2014, the Dart project authors.
 * 
 * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html
 * 
 * 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.
 * 
 * This file has been automatically generated.  Please do not edit it manually.
 * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
 */''';
    } else {
      header = '''
// Copyright (c) 2014, 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.
//
// This file has been automatically generated.  Please do not edit it manually.
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
''';
    }
    writeln(header.trim());
  }
}

/**
 * State used by [CodeGenerator].
 */
class _CodeGeneratorState {
  StringBuffer buffer = new StringBuffer();
  String nextIndent = '';
  String indent = '';
  bool indentNeeded = true;

  void write(String text) {
    List<String> lines = text.split('\n');
    for (int i = 0; i < lines.length; i++) {
      if (i == lines.length - 1 && lines[i].isEmpty) {
        break;
      }
      if (indentNeeded) {
        buffer.write(nextIndent);
        nextIndent = indent;
      }
      indentNeeded = false;
      buffer.write(lines[i]);
      if (i != lines.length - 1) {
        buffer.writeln();
        indentNeeded = true;
      }
    }
  }
}

/**
 * Mixin class for generating HTML representations of code that are suitable
 * for enclosing inside a <pre> element.
 */
abstract class HtmlCodeGenerator {
  _HtmlCodeGeneratorState _state;

  /**
   * Execute [callback], collecting any code that is output using [write],
   * [writeln], [add], or [addAll], and return the result as a list of DOM
   * nodes.
   */
  List<dom.Node> collectHtml(void callback()) {
    _HtmlCodeGeneratorState oldState = _state;
    try {
      _state = new _HtmlCodeGeneratorState();
      if (callback != null) {
        callback();
      }
      return _state.buffer;
    } finally {
      _state = oldState;
    }
  }

  /**
   * Add the given [node] to the HTML output.
   */
  void add(dom.Node node) {
    _state.add(node);
  }

  /**
   * Add the given [nodes] to the HTML output.
   */
  void addAll(Iterable<dom.Node> nodes) {
    for (dom.Node node in nodes) {
      _state.add(node);
    }
  }

  /**
   * Output text without ending the current line.
   */
  void write(Object obj) {
    _state.write(obj.toString());
  }

  /**
   * Output text, ending the current line.
   */
  void writeln([Object obj = '']) {
    _state.write('$obj\n');
  }

  /**
   * Execute [callback], indenting any code it outputs by two spaces.
   */
  void indent(void callback()) {
    String oldIndent = _state.indent;
    try {
      _state.indent += '  ';
      callback();
    } finally {
      _state.indent = oldIndent;
    }
  }

  /**
   * Execute [callback], wrapping its output in an element with the given
   * [name] and [attributes].
   */
  void element(String name, Map<String, String> attributes, [void callback()]) {
    add(makeElement(name, attributes, collectHtml(callback)));
  }
}

/**
 * State used by [HtmlCodeGenerator].
 */
class _HtmlCodeGeneratorState {
  List<dom.Node> buffer = <dom.Node>[];
  String indent = '';
  bool indentNeeded = true;

  void add(dom.Node node) {
    if (node is dom.Text) {
      write(node.text);
    } else {
      buffer.add(node);
    }
  }

  void write(String text) {
    if (text.isEmpty) {
      return;
    }
    if (indentNeeded) {
      buffer.add(new dom.Text(indent));
    }
    List<String> lines = text.split('\n');
    if (lines.last.isEmpty) {
      lines.removeLast();
      buffer.add(new dom.Text(lines.join('\n$indent') + '\n'));
      indentNeeded = true;
    } else {
      buffer.add(new dom.Text(lines.join('\n$indent')));
      indentNeeded = false;
    }
  }
}

/**
 * Type of functions used to compute the contents of a generated file.
 */
typedef String FileContentsComputer();

/**
 * Type of functions used to compute the contents of a set of generated files.
 */
typedef Map<String, FileContentsComputer> DirectoryContentsComputer();

abstract class GeneratedContent {
  FileSystemEntity get outputFile;
  bool check();
  void generate();
}

/**
 * Class representing a single output file (either generated code or generated
 * HTML).
 */
class GeneratedFile extends GeneratedContent {
  /**
   * The output file to which generated output should be written, relative to
   * the "tool/spec" directory.  This filename uses the posix path separator
   * ('/') regardless of the OS.
   */
  final String outputPath;

  /**
   * Callback function which computes the file.
   */
  final FileContentsComputer computeContents;

  GeneratedFile(this.outputPath, this.computeContents);

  /**
   * Get a File object representing the output file.
   */
  File get outputFile => new File(joinAll(posix.split(outputPath)));

  /**
   * Check whether the file has the correct contents, and return true if it
   * does.
   */
  @override
  bool check() {
    String expectedContents = computeContents();
    try {
      return expectedContents == outputFile.readAsStringSync();
    } catch (e) {
      // There was a problem reading the file (most likely because it didn't
      // exist).  Treat that the same as if the file doesn't have the expected
      // contents.
      return false;
    }
  }

  /**
   * Replace the file with the correct contents.  [spec] is the "tool/spec"
   * directory.  If [spec] is unspecified, it is assumed to be the directory
   * containing Platform.executable.
   */
  void generate() {
    outputFile.writeAsStringSync(computeContents());
  }
}

/**
 * Class representing a single output directory (either generated code or
 * generated HTML). No other content should exisit in the directory.
 */
class GeneratedDirectory extends GeneratedContent {

  /**
   * The path to the directory that will have the generated content.
   */
  final String outputDirPath;

  /**
   * Callback function which computes the directory contents.
   */
  final DirectoryContentsComputer directoryContentsComputer;

  GeneratedDirectory(this.outputDirPath, this.directoryContentsComputer);

  /**
   * Get a Directory object representing the output directory.
   */
  Directory get outputFile =>
      new Directory(joinAll(posix.split(outputDirPath)));

  /**
   * Check whether the directory has the correct contents, and return true if it
   * does.
   */
  @override
  bool check() {
    Map<String, FileContentsComputer> map = directoryContentsComputer();
    try {
      map.forEach((String file, FileContentsComputer fileContentsComputer) {
        String expectedContents = fileContentsComputer();
        File outputFile =
            new File(joinAll(posix.split(posix.join(outputDirPath, file))));
        if (expectedContents != outputFile.readAsStringSync()) {
          return false;
        }
      });
      int nonHiddenFileCount = 0;
      outputFile.listSync(
          recursive: false,
          followLinks: false).forEach((FileSystemEntity fileSystemEntity) {
         if(fileSystemEntity is File && !basename(fileSystemEntity.path).startsWith('.')) {
           nonHiddenFileCount++;
         }
      });
      if (nonHiddenFileCount != map.length) {
        // The number of files generated doesn't match the number we expected to
        // generate.
        return false;
      }
    } catch (e) {
      // There was a problem reading the file (most likely because it didn't
      // exist).  Treat that the same as if the file doesn't have the expected
      // contents.
      return false;
    }
    return true;
  }

  /**
   * Replace the directory with the correct contents.  [spec] is the "tool/spec"
   * directory.  If [spec] is unspecified, it is assumed to be the directory
   * containing Platform.executable.
   */
  @override
  void generate() {
    try {
      // delete the contents of the directory (and the directory itself)
      outputFile.deleteSync(recursive: true);
    } catch (e) {
      // Error caught while trying to delete the directory, this can happen if
      // it didn't yet exist.
    }
    // re-create the empty directory
    outputFile.createSync(recursive: true);

    // generate all of the files in the directory
    Map<String, FileContentsComputer> map = directoryContentsComputer();
    map.forEach((String file, FileContentsComputer fileContentsComputer) {
      File outputFile = new File(joinAll(posix.split(outputDirPath + file)));
      outputFile.writeAsStringSync(fileContentsComputer());
    });
  }
}
