// 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.

/// The models used to represent Dart code.
library dartdoc.element_type;

import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:dartdoc/src/model.dart';

/// Base class representing a type in Dartdoc.  It wraps a [DartType], and
/// may link to a [ModelElement].
abstract class ElementType extends Privacy {
  final DartType _type;
  final PackageGraph packageGraph;
  final DefinedElementType returnedFrom;

  ElementType(this._type, this.packageGraph, this.returnedFrom);

  factory ElementType.from(DartType f, PackageGraph packageGraph,
      [ElementType returnedFrom]) {
    if (f.element == null || f.element.kind == ElementKind.DYNAMIC) {
      return UndefinedElementType(f, packageGraph, returnedFrom);
    } else {
      ModelElement element = ModelElement.fromElement(f.element, packageGraph);
      assert(f is ParameterizedType || f is TypeParameterType);
      bool isGenericTypeAlias =
          f.element.enclosingElement is GenericTypeAliasElement;
      if (f is FunctionType) {
        assert(f is ParameterizedType);
        if (isGenericTypeAlias) {
          assert(element is! ModelFunctionAnonymous);
          return CallableGenericTypeAliasElementType(
              f, packageGraph, element, returnedFrom);
        } else {
          if (element is ModelFunctionAnonymous) {
            return CallableAnonymousElementType(
                f, packageGraph, element, returnedFrom);
          } else {
            assert(element is! ModelFunctionAnonymous);
            return CallableElementType(f, packageGraph, element, returnedFrom);
          }
        }
      } else if (isGenericTypeAlias) {
        assert(f is TypeParameterType);
        assert(element is! ModelFunctionAnonymous);
        return GenericTypeAliasElementType(
            f, packageGraph, element, returnedFrom);
      }
      if (f is TypeParameterType) {
        assert(element is! ModelFunctionAnonymous);
        return TypeParameterElementType(f, packageGraph, element, returnedFrom);
      }
      assert(f is ParameterizedType);
      assert(element is! ModelFunctionAnonymous);
      return ParameterizedElementType(f, packageGraph, element, returnedFrom);
    }
  }

  bool get canHaveParameters => false;

  // TODO(jcollins-g): change clients of ElementType to use subtypes more consistently
  // and eliminate createLinkedReturnTypeName (instead, using returnType.linkedName);
  String createLinkedReturnTypeName() => linkedName;

  bool get isTypedef => false;

  String get linkedName;

  String get name => type.name ?? type.element.name;

  String get nameWithGenerics;

  List<Parameter> get parameters => [];

  @override
  String toString() => "$type";

  DartType get type => _type;
}

/// An [ElementType] that isn't pinned to an Element (or one that is, but whose
/// element is irrelevant).
class UndefinedElementType extends ElementType {
  UndefinedElementType(
      DartType f, PackageGraph packageGraph, ElementType returnedFrom)
      : super(f, packageGraph, returnedFrom);

  @override
  bool get isPublic => true;

  @override

  /// dynamic and void are not allowed to have parameterized types.
  String get linkedName {
    if (type.isDynamic &&
        returnedFrom != null &&
        returnedFrom.element.isAsynchronous) return 'Future';
    return name;
  }

  @override
  String get nameWithGenerics => name;
}

class ParameterizedElementType extends DefinedElementType {
  ParameterizedElementType(ParameterizedType type, PackageGraph packageGraph,
      ModelElement element, ElementType returnedFrom)
      : super(type, packageGraph, element, returnedFrom);

  String _linkedName;
  @override
  String get linkedName {
    if (_linkedName == null) {
      StringBuffer buf = StringBuffer();

      buf.write(element.linkedName);

      if (!typeArguments.every((t) => t.name == 'dynamic') &&
          typeArguments.isNotEmpty) {
        buf.write('<span class="signature">');
        buf.write('&lt;<wbr><span class="type-parameter">');
        buf.writeAll(typeArguments.map((t) => t.linkedName),
            '</span>, <span class="type-parameter">');
        buf.write('</span>&gt;');
        buf.write('</span>');
      }

      _linkedName = buf.toString();
    }
    return _linkedName;
  }

  String _nameWithGenerics;
  @override
  String get nameWithGenerics {
    if (_nameWithGenerics == null) {
      StringBuffer buf = StringBuffer();

      buf.write(element.name);

      if (!typeArguments.every((t) => t.name == 'dynamic') &&
          typeArguments.isNotEmpty) {
        buf.write('&lt;<wbr><span class="type-parameter">');
        buf.writeAll(typeArguments.map((t) => t.nameWithGenerics),
            '</span>, <span class="type-parameter">');
        buf.write('</span>&gt;');
      }
      _nameWithGenerics = buf.toString();
    }
    return _nameWithGenerics;
  }
}

class TypeParameterElementType extends DefinedElementType {
  TypeParameterElementType(TypeParameterType type, PackageGraph packageGraph,
      ModelElement element, ElementType returnedFrom)
      : super(type, packageGraph, element, returnedFrom);

  @override
  String get linkedName => name;

  String _nameWithGenerics;
  @override
  String get nameWithGenerics {
    if (_nameWithGenerics == null) {
      _nameWithGenerics = name;
    }
    return _nameWithGenerics;
  }
}

/// An [ElementType] associated with an [Element].
abstract class DefinedElementType extends ElementType {
  final ModelElement _element;

  DefinedElementType(DartType type, PackageGraph packageGraph, this._element,
      ElementType returnedFrom)
      : super(type, packageGraph, returnedFrom);

  ModelElement get element {
    assert(_element != null);
    return _element;
  }

  bool get isParameterType => (type is TypeParameterType);

  /// This type is a public type if the underlying, canonical element is public.
  /// This avoids discarding the resolved type information as canonicalization
  /// would ordinarily do.
  @override
  bool get isPublic {
    Container canonicalClass =
        element.packageGraph.findCanonicalModelElementFor(element.element) ??
            element;
    return canonicalClass.isPublic;
  }

  @override
  bool get isTypedef => element is Typedef || element is ModelFunctionTypedef;

  @override
  List<Parameter> get parameters =>
      element.canHaveParameters ? element.parameters : [];

  ModelElement get returnElement => element;
  ElementType _returnType;
  ElementType get returnType {
    if (_returnType == null) {
      _returnType = ElementType.from(type, packageGraph, this);
    }
    return _returnType;
  }

  @override
  String createLinkedReturnTypeName() => returnType.linkedName;

  Iterable<ElementType> _typeArguments;
  Iterable<ElementType> get typeArguments {
    if (_typeArguments == null) {
      _typeArguments = (type as ParameterizedType)
          .typeArguments
          .map((f) => ElementType.from(f, packageGraph))
          .toList();
    }
    return _typeArguments;
  }
}

/// Any callable ElementType will mix-in this class, whether anonymous or not.
abstract class CallableElementTypeMixin implements ParameterizedElementType {
  @override
  ModelElement get returnElement => returnType is DefinedElementType
      ? (returnType as DefinedElementType).element
      : null;

  @override
  ElementType get returnType {
    if (_returnType == null) {
      _returnType = ElementType.from(type.returnType, packageGraph, this);
    }
    return _returnType;
  }

  @override
  FunctionType get type => _type;

  @override
  // TODO(jcollins-g): Rewrite this and improve object model so this doesn't
  // require type checking everywhere.
  Iterable<ElementType> get typeArguments {
    if (_typeArguments == null) {
      Iterable<DartType> dartTypeArguments;
      if (type.typeFormals.isEmpty &&
          element is! ModelFunctionAnonymous &&
          returnedFrom?.element is! ModelFunctionAnonymous) {
        dartTypeArguments = type.typeArguments;
      } else if (returnedFrom != null &&
          returnedFrom.type.element is GenericFunctionTypeElement) {
        _typeArguments = returnedFrom.typeArguments;
      } else {
        dartTypeArguments = type.typeFormals.map((f) => f.type);
      }
      if (dartTypeArguments != null) {
        _typeArguments = dartTypeArguments
            .map((f) => ElementType.from(f, packageGraph))
            .toList();
      }
    }
    return _typeArguments;
  }
}

/// A callable type that may or may not be backed by a declaration using the generic
/// function syntax.
class CallableElementType extends ParameterizedElementType
    with CallableElementTypeMixin {
  CallableElementType(FunctionType t, PackageGraph packageGraph,
      ModelElement element, ElementType returnedFrom)
      : super(t, packageGraph, element, returnedFrom);

  @override
  String get linkedName {
    if (name != null && name.isNotEmpty) return super.linkedName;
    return '${nameWithGenerics}(${element.linkedParams(showNames: false).trim()}) → ${returnType.linkedName}';
  }
}

/// This is an anonymous function using the generic function syntax (declared
/// literally with "Function").
class CallableAnonymousElementType extends CallableElementType {
  CallableAnonymousElementType(FunctionType t, PackageGraph packageGraph,
      ModelElement element, ElementType returnedFrom)
      : super(t, packageGraph, element, returnedFrom);
  @override
  String get name => 'Function';

  @override
  String get linkedName {
    if (_linkedName == null) {
      _linkedName =
          '${returnType.linkedName} ${super.linkedName}<span class="signature">(${element.linkedParams()})</span>';
    }
    return _linkedName;
  }
}

/// Types backed by a [GenericTypeAliasElement] that may or may not be callable.
abstract class GenericTypeAliasElementTypeMixin {}

/// A non-callable type backed by a [GenericTypeAliasElement].
class GenericTypeAliasElementType extends TypeParameterElementType
    with GenericTypeAliasElementTypeMixin {
  GenericTypeAliasElementType(TypeParameterType t, PackageGraph packageGraph,
      ModelElement element, ElementType returnedFrom)
      : super(t, packageGraph, element, returnedFrom);
}

/// A Callable generic type alias that may or may not have a name.
class CallableGenericTypeAliasElementType extends ParameterizedElementType
    with CallableElementTypeMixin, GenericTypeAliasElementTypeMixin {
  CallableGenericTypeAliasElementType(FunctionType t, PackageGraph packageGraph,
      ModelElement element, ElementType returnedFrom)
      : super(t, packageGraph, element, returnedFrom);

  ModelElement _returnElement;
  @override
  ModelElement get returnElement {
    if (_returnElement == null) {
      _returnElement =
          ModelElement.fromElement(type.element.enclosingElement, packageGraph);
    }
    return _returnElement;
  }

  @override
  ElementType get returnType {
    if (_returnType == null) {
      _returnType =
          ElementType.from(returnElement.modelType.type, packageGraph, this);
    }
    return _returnType;
  }
}
