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

part of protoc;

class FileGenerator extends ProtobufContainer {
  final FileDescriptorProto _fileDescriptor;
  final ProtobufContainer _parent;
  final GenerationContext _context;

  final List<EnumGenerator> enumGenerators = <EnumGenerator>[];
  final List<MessageGenerator> messageGenerators = <MessageGenerator>[];
  final List<ExtensionGenerator> extensionGenerators = <ExtensionGenerator>[];

  FileGenerator(this._fileDescriptor, this._parent, this._context) {
    _context.register(this);
    // Load and register all enum and message types.
    for (EnumDescriptorProto enumType in _fileDescriptor.enumType) {
      enumGenerators.add(new EnumGenerator(enumType, this, _context));
    }
    for (DescriptorProto messageType in _fileDescriptor.messageType) {
      messageGenerators.add(new MessageGenerator(messageType, this, _context));
    }
    for (FieldDescriptorProto extension in _fileDescriptor.extension) {
      extensionGenerators.add(
          new ExtensionGenerator(extension, this, _context));
    }
  }

  String get package => _fileDescriptor.package;
  String get classname => '';
  String get fqname => '.${_fileDescriptor.package}';

  // Extract the filename from a URI and remove the extension.
  String _fileNameWithoutExtension(Uri filePath) {
    String fileName = filePath.pathSegments.last;
    int index = fileName.lastIndexOf(".");
    return index == -1 ? fileName : fileName.substring(0, index);
  }

  // Create the URI for the generated Dart file from the URI of the
  // .proto file.
  Uri _generatedFilePath(Uri protoFilePath) {
    var dartFileName = _fileNameWithoutExtension(protoFilePath) + ".pb.dart";
    return protoFilePath.resolve(dartFileName);
  }

  String _generateClassName(Uri protoFilePath) {
    String s = _fileNameWithoutExtension(protoFilePath).replaceAll('-', '_');
    return '${s[0].toUpperCase()}${s.substring(1)}';
  }

  String _generateLibraryName(Uri protoFilePath) {
    if (_fileDescriptor.package != '') return _fileDescriptor.package;
    return _fileNameWithoutExtension(protoFilePath).replaceAll('-', '_');
  }

  Uri _relative(Uri target, Uri base) {
    // Ignore the last segment of the base.
    List<String> baseSegments =
        base.pathSegments.sublist(0, base.pathSegments.length - 1);
    List<String> targetSegments = target.pathSegments;
    if (baseSegments.length == 1 && baseSegments[0] == '.') {
      baseSegments = [];
    }
    if (targetSegments.length == 1 && targetSegments[0] == '.') {
      targetSegments = [];
    }
    int common = 0;
    int length = min(targetSegments.length, baseSegments.length);
    while (common < length && targetSegments[common] == baseSegments[common]) {
      common++;
    }

    final segments = <String>[];
    if (common < baseSegments.length && baseSegments[common] == '..') {
      throw new ArgumentError(
          "Cannot create a relative path from $base to $target");
    }
    for (int i = common; i < baseSegments.length; i++) {
      segments.add('..');
    }
    for (int i = common; i < targetSegments.length; i++) {
      segments.add('${targetSegments[i]}');
    }
    if (segments.isEmpty) {
      segments.add('.');
    }
    return new Uri(pathSegments: segments);
  }

  CodeGeneratorResponse_File generateResponse() {
    MemoryWriter writer = new MemoryWriter();
    IndentingWriter out = new IndentingWriter('  ', writer);

    generate(out);

    Uri filePath = new Uri(scheme: 'file', path: _fileDescriptor.name);
    return new CodeGeneratorResponse_File()
        ..name = _generatedFilePath(filePath).path
        ..content = writer.toString();
  }

  void generate(IndentingWriter out) {
    Uri filePath = new Uri.file(_fileDescriptor.name);
    if (filePath.isAbsolute) {
        // protoc should never generate a file descriptor with an absolute path.
        throw("FAILURE: File with an absolute path is not supported");
    }

    String libraryName = _generateLibraryName(filePath);

    out.println(
      '///\n'
      '//  Generated code. Do not modify.\n'
      '///\n'
      'library $libraryName;\n'
      '\n'
      "import 'package:fixnum/fixnum.dart';\n"
      "import 'package:protobuf/protobuf.dart';"
    );

    for (String import in _fileDescriptor.dependency) {
      Uri importPath = new Uri.file(import);
      if (importPath.isAbsolute) {
        // protoc should never generate an import with an absolute path.
        throw("FAILURE: Import with absolute path is not supported");
      }
      // Create a relative path from the current file to the import.
      Uri relativeProtoPath = _relative(importPath, filePath);
      // Find the file generator for this import as it contains the
      // package name.
      FileGenerator fileGenerator = _context.lookupFile(import);
      out.print("import '${_generatedFilePath(relativeProtoPath)}'");
      if (package != fileGenerator.package && !fileGenerator.package.isEmpty) {
        out.print(' as ${fileGenerator.packageImportPrefix}');
      }
      out.println(';');
    }
    out.println('');

    // Initialize Field.
    for (MessageGenerator m in messageGenerators) {
      m.initializeFields();
    }

    // Generate code.
    for (EnumGenerator e in enumGenerators) {
      e.generate(out);
    }
    for (MessageGenerator m in messageGenerators) {
      m.generate(out);
    }

    // Generate code for extensions defined at top-level using a class
    // name derived from the file name.
    if (!extensionGenerators.isEmpty) {
      // TODO(antonm): do not generate a class.
      String className = _generateClassName(filePath);
      out.addBlock('class $className {', '}\n', () {
        for (ExtensionGenerator x in extensionGenerators) {
          x.generate(out);
        }
        out.println('static void registerAllExtensions(ExtensionRegistry '
            'registry) {');
        for (ExtensionGenerator x in extensionGenerators) {
          out.println('  registry.add(${x.name});');
        }
        out.println('}');
      });
    }
  }
}

class GenerationContext {
  final GenerationOptions options;
  final Map<String, ProtobufContainer> _registry =
      <String, ProtobufContainer>{};
  final Map<String, FileGenerator> _files =
      <String, FileGenerator>{};

  GenerationContext(this.options);

  void register(ProtobufContainer container) {
    _registry[container.fqname] = container;
    if (container is FileGenerator) {
      _files[container._fileDescriptor.name] = container;
    }
  }

  ProtobufContainer operator [](String fqname) => _registry[fqname];

  FileGenerator lookupFile(String name) => _files[name];
}
