// Copyright (c) 2019, 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.
library fasta.collections;

import 'dart:core' hide MapEntry;

import 'package:kernel/ast.dart'
    show
        DartType,
        Expression,
        MapEntry,
        NullLiteral,
        Statement,
        TreeNode,
        VariableDeclaration,
        setParents,
        transformList,
        visitList;

import 'package:kernel/type_environment.dart' show TypeEnvironment;

import 'package:kernel/visitor.dart'
    show
        ExpressionVisitor,
        ExpressionVisitor1,
        Transformer,
        TreeVisitor,
        Visitor;

import '../messages.dart'
    show templateExpectedAfterButGot, templateExpectedButGot;

import '../problems.dart' show getFileUri, unsupported;

import '../type_inference/inference_helper.dart' show InferenceHelper;

/// Mixin for spread and control-flow elements.
///
/// Spread and control-flow elements are not truly expressions and they cannot
/// appear in arbitrary expression contexts in the Kernel program.  They can
/// only appear as elements in list or set literals.  They are translated into
/// a lower-level representation and never serialized to .dill files.
mixin ControlFlowElement on Expression {
  /// Spread and control-flow elements are not expressions and do not have a
  /// static type.
  @override
  DartType getStaticType(TypeEnvironment types) {
    return unsupported("getStaticType", fileOffset, getFileUri(this));
  }

  @override
  accept(ExpressionVisitor<Object> v) => v.defaultExpression(this);

  @override
  accept1(ExpressionVisitor1<Object, Object> v, arg) =>
      v.defaultExpression(this, arg);
}

/// A spread element in a list or set literal.
class SpreadElement extends Expression with ControlFlowElement {
  Expression expression;
  bool isNullAware;

  /// The type of the elements of the collection that [expression] evaluates to.
  ///
  /// It is set during type inference and is used to add appropriate type casts
  /// during the desugaring.
  DartType elementType;

  SpreadElement(this.expression, this.isNullAware) {
    expression?.parent = this;
  }

  @override
  visitChildren(Visitor<Object> v) {
    expression?.accept(v);
  }

  @override
  transformChildren(Transformer v) {
    if (expression != null) {
      expression = expression.accept(v);
      expression?.parent = this;
    }
  }
}

/// An 'if' element in a list or set literal.
class IfElement extends Expression with ControlFlowElement {
  Expression condition;
  Expression then;
  Expression otherwise;

  IfElement(this.condition, this.then, this.otherwise) {
    condition?.parent = this;
    then?.parent = this;
    otherwise?.parent = this;
  }

  @override
  visitChildren(Visitor<Object> v) {
    condition?.accept(v);
    then?.accept(v);
    otherwise?.accept(v);
  }

  @override
  transformChildren(Transformer v) {
    if (condition != null) {
      condition = condition.accept(v);
      condition?.parent = this;
    }
    if (then != null) {
      then = then.accept(v);
      then?.parent = this;
    }
    if (otherwise != null) {
      otherwise = otherwise.accept(v);
      otherwise?.parent = this;
    }
  }
}

/// A 'for' element in a list or set literal.
class ForElement extends Expression with ControlFlowElement {
  final List<VariableDeclaration> variables; // May be empty, but not null.
  Expression condition; // May be null.
  final List<Expression> updates; // May be empty, but not null.
  Expression body;

  ForElement(this.variables, this.condition, this.updates, this.body) {
    setParents(variables, this);
    condition?.parent = this;
    setParents(updates, this);
    body?.parent = this;
  }

  @override
  visitChildren(Visitor<Object> v) {
    visitList(variables, v);
    condition?.accept(v);
    visitList(updates, v);
    body?.accept(v);
  }

  @override
  transformChildren(Transformer v) {
    transformList(variables, v, this);
    if (condition != null) {
      condition = condition.accept(v);
      condition?.parent = this;
    }
    transformList(updates, v, this);
    if (body != null) {
      body = body.accept(v);
      body?.parent = this;
    }
  }
}

/// A 'for-in' element in a list or set literal.
class ForInElement extends Expression with ControlFlowElement {
  VariableDeclaration variable; // Has no initializer.
  Expression iterable;
  Statement prologue; // May be null.
  Expression body;
  Expression problem; // May be null.
  bool isAsync; // True if this is an 'await for' loop.

  ForInElement(
      this.variable, this.iterable, this.prologue, this.body, this.problem,
      {this.isAsync: false}) {
    variable?.parent = this;
    iterable?.parent = this;
    prologue?.parent = this;
    body?.parent = this;
    problem?.parent = this;
  }

  visitChildren(Visitor<Object> v) {
    variable?.accept(v);
    iterable?.accept(v);
    prologue?.accept(v);
    body?.accept(v);
    problem?.accept(v);
  }

  transformChildren(Transformer v) {
    if (variable != null) {
      variable = variable.accept(v);
      variable?.parent = this;
    }
    if (iterable != null) {
      iterable = iterable.accept(v);
      iterable?.parent = this;
    }
    if (prologue != null) {
      prologue = prologue.accept(v);
      prologue?.parent = this;
    }
    if (body != null) {
      body = body.accept(v);
      body?.parent = this;
    }
    if (problem != null) {
      problem = problem.accept(v);
      problem?.parent = this;
    }
  }
}

mixin ControlFlowMapEntry implements MapEntry {
  @override
  Expression get key {
    throw UnsupportedError('ControlFlowMapEntry.key getter');
  }

  @override
  void set key(Expression expr) {
    throw UnsupportedError('ControlFlowMapEntry.key setter');
  }

  @override
  Expression get value {
    throw UnsupportedError('ControlFlowMapEntry.value getter');
  }

  @override
  void set value(Expression expr) {
    throw UnsupportedError('ControlFlowMapEntry.value setter');
  }

  @override
  accept(TreeVisitor<Object> v) => v.defaultTreeNode(this);
}

/// A spread element in a map literal.
class SpreadMapEntry extends TreeNode with ControlFlowMapEntry {
  Expression expression;
  bool isNullAware;

  /// The type of the map entries of the map that [expression] evaluates to.
  ///
  /// It is set during type inference and is used to add appropriate type casts
  /// during the desugaring.
  DartType entryType;

  SpreadMapEntry(this.expression, this.isNullAware) {
    expression?.parent = this;
  }

  @override
  visitChildren(Visitor<Object> v) {
    expression?.accept(v);
  }

  @override
  transformChildren(Transformer v) {
    if (expression != null) {
      expression = expression.accept(v);
      expression?.parent = this;
    }
  }
}

/// An 'if' element in a map literal.
class IfMapEntry extends TreeNode with ControlFlowMapEntry {
  Expression condition;
  MapEntry then;
  MapEntry otherwise;

  IfMapEntry(this.condition, this.then, this.otherwise) {
    condition?.parent = this;
    then?.parent = this;
    otherwise?.parent = this;
  }

  @override
  visitChildren(Visitor<Object> v) {
    condition?.accept(v);
    then?.accept(v);
    otherwise?.accept(v);
  }

  @override
  transformChildren(Transformer v) {
    if (condition != null) {
      condition = condition.accept(v);
      condition?.parent = this;
    }
    if (then != null) {
      then = then.accept(v);
      then?.parent = this;
    }
    if (otherwise != null) {
      otherwise = otherwise.accept(v);
      otherwise?.parent = this;
    }
  }
}

/// A 'for' element in a map literal.
class ForMapEntry extends TreeNode with ControlFlowMapEntry {
  final List<VariableDeclaration> variables; // May be empty, but not null.
  Expression condition; // May be null.
  final List<Expression> updates; // May be empty, but not null.
  MapEntry body;

  ForMapEntry(this.variables, this.condition, this.updates, this.body) {
    setParents(variables, this);
    condition?.parent = this;
    setParents(updates, this);
    body?.parent = this;
  }

  @override
  visitChildren(Visitor<Object> v) {
    visitList(variables, v);
    condition?.accept(v);
    visitList(updates, v);
    body?.accept(v);
  }

  @override
  transformChildren(Transformer v) {
    transformList(variables, v, this);
    if (condition != null) {
      condition = condition.accept(v);
      condition?.parent = this;
    }
    transformList(updates, v, this);
    if (body != null) {
      body = body.accept(v);
      body?.parent = this;
    }
  }
}

/// A 'for-in' element in a map literal.
class ForInMapEntry extends TreeNode with ControlFlowMapEntry {
  VariableDeclaration variable; // Has no initializer.
  Expression iterable;
  Statement prologue; // May be null.
  MapEntry body;
  Expression problem; // May be null.
  bool isAsync; // True if this is an 'await for' loop.

  ForInMapEntry(
      this.variable, this.iterable, this.prologue, this.body, this.problem,
      {this.isAsync: false}) {
    variable?.parent = this;
    iterable?.parent = this;
    prologue?.parent = this;
    body?.parent = this;
    problem?.parent = this;
  }

  visitChildren(Visitor<Object> v) {
    variable?.accept(v);
    iterable?.accept(v);
    prologue?.accept(v);
    body?.accept(v);
    problem?.accept(v);
  }

  transformChildren(Transformer v) {
    if (variable != null) {
      variable = variable.accept(v);
      variable?.parent = this;
    }
    if (iterable != null) {
      iterable = iterable.accept(v);
      iterable?.parent = this;
    }
    if (prologue != null) {
      prologue = prologue.accept(v);
      prologue?.parent = this;
    }
    if (body != null) {
      body = body.accept(v);
      body?.parent = this;
    }
    if (problem != null) {
      problem = problem.accept(v);
      problem?.parent = this;
    }
  }
}

Expression convertToElement(MapEntry entry, InferenceHelper helper) {
  if (entry is SpreadMapEntry) {
    return new SpreadElement(entry.expression, entry.isNullAware)
      ..fileOffset = entry.expression.fileOffset;
  }
  if (entry is IfMapEntry) {
    return new IfElement(
        entry.condition,
        convertToElement(entry.then, helper),
        entry.otherwise == null
            ? null
            : convertToElement(entry.otherwise, helper))
      ..fileOffset = entry.fileOffset;
  }
  if (entry is ForMapEntry) {
    return new ForElement(entry.variables, entry.condition, entry.updates,
        convertToElement(entry.body, helper))
      ..fileOffset = entry.fileOffset;
  }
  if (entry is ForInMapEntry) {
    return new ForInElement(entry.variable, entry.iterable, entry.prologue,
        convertToElement(entry.body, helper), entry.problem,
        isAsync: entry.isAsync)
      ..fileOffset = entry.fileOffset;
  }
  return helper.desugarSyntheticExpression(helper.buildProblem(
    templateExpectedButGot.withArguments(','),
    entry.fileOffset,
    1,
  ));
}

bool isConvertibleToMapEntry(Expression element) {
  if (element is SpreadElement) return true;
  if (element is IfElement) {
    return isConvertibleToMapEntry(element.then) &&
        (element.otherwise == null ||
            isConvertibleToMapEntry(element.otherwise));
  }
  if (element is ForElement) {
    return isConvertibleToMapEntry(element.body);
  }
  if (element is ForInElement) {
    return isConvertibleToMapEntry(element.body);
  }
  return false;
}

MapEntry convertToMapEntry(Expression element, InferenceHelper helper) {
  if (element is SpreadElement) {
    return new SpreadMapEntry(element.expression, element.isNullAware)
      ..fileOffset = element.expression.fileOffset;
  }
  if (element is IfElement) {
    return new IfMapEntry(
        element.condition,
        convertToMapEntry(element.then, helper),
        element.otherwise == null
            ? null
            : convertToMapEntry(element.otherwise, helper))
      ..fileOffset = element.fileOffset;
  }
  if (element is ForElement) {
    return new ForMapEntry(element.variables, element.condition,
        element.updates, convertToMapEntry(element.body, helper))
      ..fileOffset = element.fileOffset;
  }
  if (element is ForInElement) {
    return new ForInMapEntry(
        element.variable,
        element.iterable,
        element.prologue,
        convertToMapEntry(element.body, helper),
        element.problem,
        isAsync: element.isAsync)
      ..fileOffset = element.fileOffset;
  }
  return new MapEntry(
      helper.desugarSyntheticExpression(helper.buildProblem(
        templateExpectedAfterButGot.withArguments(':'),
        element.fileOffset,
        // TODO(danrubel): what is the length of the expression?
        1,
      )),
      new NullLiteral());
}
