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

library kernel.transformations.scanner;

import '../ast.dart';

abstract class Scanner<X extends TreeNode?, Y extends TreeNode?> {
  final Scanner<Y, TreeNode?>? next;
  Scanner(this.next);
  bool predicate(X x);
  ScanResult<X, Y> scan(TreeNode node);
}

class ScanResult<X extends TreeNode?, Y extends TreeNode?> {
  Map<X, ScanResult<Y, TreeNode?>?> targets = new Map();
  Map<X, ScanError>? errors;

  @override
  String toString() => 'ScanResult<$X,$Y>';
}

class ScanError {}

abstract class ClassScanner<Y extends TreeNode?> implements Scanner<Class, Y> {
  @override
  final Scanner<Y, TreeNode?>? next;

  ClassScanner(this.next);

  @override
  bool predicate(Class node);

  @override
  ScanResult<Class, Y> scan(TreeNode node) {
    ScanResult<Class, Y> result = new ScanResult<Class, Y>();

    if (node is Class) {
      if (predicate(node)) {
        result.targets[node] = next?.scan(node);
        // TODO(cstefantsova): set result.errors when specification is landed,
        // same with all other places where targets is set
      }
    } else if (node is Library) {
      _scanLibrary(node, result);
    } else if (node is Component) {
      _scanComponent(node, result);
    }

    return result;
  }

  void _scanLibrary(Library library, ScanResult<Class, Y> result) {
    for (Class cls in library.classes) {
      if (predicate(cls)) {
        result.targets[cls] = next?.scan(cls);
      }
    }
  }

  void _scanComponent(Component component, ScanResult<Class, Y> result) {
    for (Library library in component.libraries) {
      _scanLibrary(library, result);
    }
  }
}

abstract class FieldScanner<Y extends TreeNode> implements Scanner<Field, Y> {
  @override
  final Scanner<Y, TreeNode>? next;

  FieldScanner(this.next);

  @override
  bool predicate(Field node);

  @override
  ScanResult<Field, Y> scan(TreeNode node) {
    ScanResult<Field, Y> result = new ScanResult<Field, Y>();

    if (node is Field) {
      _scanField(node, result);
    } else if (node is Class) {
      _scanClass(node, result);
    } else if (node is Library) {
      _scanLibrary(node, result);
    } else if (node is Component) {
      _scanComponent(node, result);
    }

    return result;
  }

  void _scanField(Field field, ScanResult<Field, Y> result) {
    if (predicate(field)) {
      result.targets[field] = next?.scan(field);
    }
  }

  void _scanClass(Class cls, ScanResult<Field, Y> result) {
    for (Field field in cls.fields) {
      _scanField(field, result);
    }
  }

  void _scanLibrary(Library library, ScanResult<Field, Y> result) {
    for (Class cls in library.classes) {
      _scanClass(cls, result);
    }
    for (Field field in library.fields) {
      _scanField(field, result);
    }
  }

  void _scanComponent(Component component, ScanResult<Field, Y> result) {
    for (Library library in component.libraries) {
      _scanLibrary(library, result);
    }
  }
}

abstract class MemberScanner<Y extends TreeNode> implements Scanner<Member, Y> {
  @override
  final Scanner<Y, TreeNode?>? next;

  MemberScanner(this.next);

  @override
  bool predicate(Member node);

  @override
  ScanResult<Member, Y> scan(TreeNode node) {
    ScanResult<Member, Y> result = new ScanResult<Member, Y>();

    if (node is Member) {
      _scanMember(node, result);
    } else if (node is Class) {
      _scanClass(node, result);
    } else if (node is Library) {
      _scanLibrary(node, result);
    } else if (node is Component) {
      _scanComponent(node, result);
    }

    return result;
  }

  void _scanMember(Member member, ScanResult<Member, Y> result) {
    if (predicate(member)) {
      result.targets[member] = next?.scan(member);
    }
  }

  void _scanClass(Class cls, ScanResult<Member, Y> result) {
    for (Member member in cls.members) {
      _scanMember(member, result);
    }
  }

  void _scanLibrary(Library library, ScanResult<Member, Y> result) {
    for (Class cls in library.classes) {
      _scanClass(cls, result);
    }
    for (Member member in library.members) {
      _scanMember(member, result);
    }
  }

  void _scanComponent(Component component, ScanResult<Member, Y> result) {
    for (Library library in component.libraries) {
      _scanLibrary(library, result);
    }
  }
}

abstract class ProcedureScanner<Y extends TreeNode?>
    implements Scanner<Procedure, Y> {
  @override
  final Scanner<Y, TreeNode>? next;

  ProcedureScanner(this.next);

  @override
  bool predicate(Procedure node);

  @override
  ScanResult<Procedure, Y> scan(TreeNode node) {
    ScanResult<Procedure, Y> result = new ScanResult<Procedure, Y>();

    if (node is Procedure) {
      _scanProcedure(node, result);
    } else if (node is Class) {
      _scanClass(node, result);
    } else if (node is Library) {
      _scanLibrary(node, result);
    } else if (node is Component) {
      _scanComponent(node, result);
    }

    return result;
  }

  void _scanProcedure(Procedure procedure, ScanResult<Procedure, Y> result) {
    if (predicate(procedure)) {
      result.targets[procedure] = next?.scan(procedure);
    }
  }

  void _scanClass(Class cls, ScanResult<Procedure, Y> result) {
    for (Procedure procedure in cls.procedures) {
      _scanProcedure(procedure, result);
    }
  }

  void _scanLibrary(Library library, ScanResult<Procedure, Y> result) {
    for (Class cls in library.classes) {
      _scanClass(cls, result);
    }
    for (Procedure procedure in library.procedures) {
      _scanProcedure(procedure, result);
    }
  }

  void _scanComponent(Component component, ScanResult<Procedure, Y> result) {
    for (Library library in component.libraries) {
      _scanLibrary(library, result);
    }
  }
}

abstract class ExpressionScanner<Y extends TreeNode>
    extends RecursiveResultVisitor<void> implements Scanner<Expression, Y> {
  @override
  final Scanner<Y, TreeNode>? next;
  ScanResult<Expression, Y>? _result;

  ExpressionScanner(this.next);

  @override
  bool predicate(Expression node);

  @override
  ScanResult<Expression, Y> scan(TreeNode node) {
    ScanResult<Expression, Y> result =
        _result = new ScanResult<Expression, Y>();
    node.accept(this);
    _result = null;
    return result;
  }

  void visitExpression(Expression node) {
    if (predicate(node)) {
      _result!.targets[node] = next?.scan(node);
      // TODO: Update result.errors.
    }
  }
}

abstract class MethodInvocationScanner<Y extends TreeNode?>
    extends RecursiveVisitor
    implements Scanner<InstanceInvocationExpression, Y> {
  @override
  final Scanner<Y, TreeNode>? next;
  ScanResult<InstanceInvocationExpression, Y>? _result;

  MethodInvocationScanner(this.next);

  @override
  bool predicate(InstanceInvocationExpression node);

  @override
  ScanResult<InstanceInvocationExpression, Y> scan(TreeNode node) {
    ScanResult<InstanceInvocationExpression, Y> result =
        _result = new ScanResult<InstanceInvocationExpression, Y>();
    node.accept(this);
    _result = null;
    return result;
  }

  @override
  void visitInstanceInvocation(InstanceInvocation node) {
    if (predicate(node)) {
      _result!.targets[node] = next?.scan(node);
      // TODO: Update result.errors.
    }
  }
}
