// 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 '../ast.dart';
import '../core_types.dart';

DartType computeFutureValueType(CoreTypes coreTypes, DartType type) {
  return type.accept1(const FutureValueTypeVisitor(), coreTypes);
}

class FutureValueTypeVisitor implements DartTypeVisitor1<DartType, CoreTypes> {
  /// Helper function invoked on unknown implementers of [DartType].
  ///
  /// Its arguments are the unhandled type and the function that can be invoked
  /// from within the handler on parts of the unknown type to recursively call
  /// the visitor.  If not set, an exception is thrown then an unhandled
  /// implementer of [DartType] is encountered.
  final DartType Function(DartType node, CoreTypes coreTypes,
          DartType Function(DartType node, CoreTypes coreTypes) recursor)
      unhandledTypeHandler;

  const FutureValueTypeVisitor({this.unhandledTypeHandler});

  DartType visit(DartType node, CoreTypes coreTypes) =>
      node.accept1(this, coreTypes);

  @override
  DartType defaultDartType(DartType node, CoreTypes coreTypes) {
    if (unhandledTypeHandler == null) {
      throw new UnsupportedError("Unsupported type '${node.runtimeType}'.");
    } else {
      return unhandledTypeHandler(node, coreTypes, visit);
    }
  }

  @override
  DartType visitBottomType(BottomType node, CoreTypes coreTypes) {
    // Otherwise, for all S, futureValueType(S) = Object?.
    return coreTypes.objectNullableRawType;
  }

  @override
  DartType visitDynamicType(DynamicType node, CoreTypes coreTypes) {
    // futureValueType(dynamic) = dynamic.
    return node;
  }

  @override
  DartType visitFunctionType(FunctionType node, CoreTypes coreTypes) {
    // Otherwise, for all S, futureValueType(S) = Object?.
    return coreTypes.objectNullableRawType;
  }

  @override
  DartType visitInterfaceType(InterfaceType node, CoreTypes coreTypes) {
    if (node.classNode == coreTypes.futureClass) {
      // futureValueType(Future<S>) = S, for all S.
      return node.typeArguments.single;
    }
    // Otherwise, for all S, futureValueType(S) = Object?.
    return coreTypes.objectNullableRawType;
  }

  @override
  DartType visitFutureOrType(FutureOrType node, CoreTypes coreTypes) {
    // futureValueType(FutureOr<S>) = S, for all S.
    return node.typeArgument;
  }

  @override
  DartType visitInvalidType(InvalidType node, CoreTypes coreTypes) {
    // Return the invalid type itself to continue the encapsulation of the
    // error state.
    return node;
  }

  @override
  DartType visitNeverType(DartType node, CoreTypes coreTypes) {
    // Otherwise, for all S, futureValueType(S) = Object?.
    return coreTypes.objectNullableRawType;
  }

  @override
  DartType visitTypeParameterType(DartType node, CoreTypes coreTypes) {
    // Otherwise, for all S, futureValueType(S) = Object?.
    return coreTypes.objectNullableRawType;
  }

  @override
  DartType visitTypedefType(DartType node, CoreTypes coreTypes) {
    // Otherwise, for all S, futureValueType(S) = Object?.
    return coreTypes.objectNullableRawType;
  }

  @override
  DartType visitVoidType(DartType node, CoreTypes coreTypes) {
    // futureValueType(void) = void.
    return node;
  }
}
