// Copyright (c) 2023, 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 '../elements/elements.dart';
import 'visitor.dart';

String _toJavaBinaryName(String kotlinBinaryName) {
  final binaryName =
      kotlinBinaryName.replaceAll('.', r'$').replaceAll('/', '.');
  return const {
        'kotlin.Any': 'java.lang.Object',
        'kotlin.Byte': 'java.lang.Byte',
        'kotlin.Short': 'java.lang.Short',
        'kotlin.Int': 'java.lang.Integer',
        'kotlin.Long': 'java.lang.Long',
        'kotlin.Char': 'java.lang.Character',
        'kotlin.Float': 'java.lang.Float',
        'kotlin.Double': 'java.lang.Double',
        'kotlin.Boolean': 'java.lang.Boolean',
        'kotlin.Cloneable': 'java.lang.Cloneable',
        'kotlin.Comparable': 'java.lang.Comparable',
        'kotlin.Enum': 'java.lang.Enum',
        'kotlin.Annotation': 'java.lang.annotation.Annotation',
        'kotlin.CharSequence': 'java.lang.CharSequence',
        'kotlin.String': 'java.lang.String',
        'kotlin.Number': 'java.lang.Number',
        'kotlin.Throwable': 'java.lang.Throwable',
      }[binaryName] ??
      binaryName;
}

/// A [Visitor] that adds the the information from Kotlin's metadata to the Java
/// classes and methods.
class KotlinProcessor extends Visitor<Classes, void> with TopLevelVisitor {
  @override
  final GenerationStage stage = GenerationStage.kotlinProcessor;

  @override
  void visit(Classes node) {
    final classProcessor = _KotlinClassProcessor();
    for (final classDecl in node.decls.values) {
      classDecl.accept(classProcessor);
    }
  }
}

class _KotlinClassProcessor extends Visitor<ClassDecl, void> {
  @override
  void visit(ClassDecl node) {
    if (node.kotlinClass == null && node.kotlinPackage == null) {
      return;
    }
    // This [ClassDecl] is actually a Kotlin class.
    if (node.kotlinClass != null) {
      for (var i = 0; i < node.kotlinClass!.typeParameters.length; ++i) {
        node.typeParams[i].accept(
            _KotlinTypeParamProcessor(node.kotlinClass!.typeParameters[i]));
      }
      if (node.superclass case final superClass?) {
        final kotlinSuperTypes = node.kotlinClass!.superTypes.where(
          (superType) =>
              _toJavaBinaryName(superType.name ?? '') == superClass.name,
        );
        if (kotlinSuperTypes.isNotEmpty) {
          superClass.accept(_KotlinTypeProcessor(kotlinSuperTypes.single));
        }
      }
    }

    // Matching fields and properties from the metadata.
    final properties = <String, KotlinProperty>{};
    final getters = <String, KotlinProperty>{};
    final setters = <String, KotlinProperty>{};
    final kotlinProperties =
        (node.kotlinClass?.properties ?? node.kotlinPackage?.properties)!;
    for (final property in kotlinProperties) {
      if (property.fieldName case final fieldName?) {
        properties[fieldName] = property;
      }
      if (property.getterName case final getterName?) {
        final getterSignature = getterName + property.getterDescriptor!;
        getters[getterSignature] = property;
      }
      if (property.setterName case final setterName?) {
        final setterSignature = setterName + property.setterDescriptor!;
        setters[setterSignature] = property;
      }
    }
    for (final field in node.fields) {
      if (properties[field.name] case final property?) {
        field.accept(_KotlinPropertyProcessor(property));
      }
    }
    // Matching methods and functions from the metadata.
    final functions = <String, KotlinFunction>{};
    final kotlinFunctions =
        (node.kotlinClass?.functions ?? node.kotlinPackage?.functions)!;
    for (final function in kotlinFunctions) {
      final signature = function.name + function.descriptor;
      functions[signature] = function;
    }
    final constructors = <String, KotlinConstructor>{};
    final kotlinConstructors = node.kotlinClass?.constructors ?? [];
    for (final constructor in kotlinConstructors) {
      final signature = constructor.name + constructor.descriptor;
      constructors[signature] = constructor;
    }
    for (final method in node.methods) {
      final signature = method.name + method.descriptor!;
      if (functions[signature] case final function?) {
        method.accept(_KotlinMethodProcessor(function));
      } else if (constructors[signature] case final constructor?) {
        method.accept(_KotlinConstructorProcessor(constructor));
      } else if (getters[signature] case final getter?) {
        method.accept(_KotlinGetterProcessor(getter));
      } else if (setters[signature] case final setter?) {
        method.accept(_KotlinSetterProcessor(setter));
      }
    }
  }
}

void _processParams(
    List<Param> params, List<KotlinValueParameter> kotlinParams) {
  if (params.length != kotlinParams.length) {
    return;
  }
  for (var i = 0; i < params.length; ++i) {
    params[i].accept(_KotlinParamProcessor(kotlinParams[i]));
  }
}

class _KotlinMethodProcessor extends Visitor<Method, void> {
  final KotlinFunction function;

  _KotlinMethodProcessor(this.function);

  @override
  void visit(Method node) {
    _processParams(node.params, function.valueParameters);
    node.kotlinFunction = function;
    for (var i = 0; i < node.typeParams.length; ++i) {
      node.typeParams[i]
          .accept(_KotlinTypeParamProcessor(function.typeParameters[i]));
    }
    if (function.isSuspend) {
      const kotlinContinutationType = 'kotlin.coroutines.Continuation';
      assert(node.params.isNotEmpty &&
          node.params.last.type is DeclaredType &&
          node.params.last.type.name == kotlinContinutationType);
      var continuationType =
          (node.params.last.type as DeclaredType).params.firstOrNull;
      if (continuationType != null &&
          continuationType is Wildcard &&
          continuationType.superBound != null) {
        continuationType = continuationType.superBound!;
      }
      node.asyncReturnType = continuationType == null
          ? DeclaredType.object.clone()
          : continuationType.clone();
      node.asyncReturnType!.accept(_KotlinTypeProcessor(function.returnType));

      if (!node.asyncReturnType!.isNullable) {
        node.returnType.annotations ??= [];
        node.returnType.annotations!.add(Annotation.nonNull);
      }
    } else {
      node.returnType.accept(_KotlinTypeProcessor(function.returnType));
    }
  }
}

class _KotlinConstructorProcessor extends Visitor<Method, void> {
  final KotlinConstructor constructor;

  _KotlinConstructorProcessor(this.constructor);

  @override
  void visit(Method node) {
    _processParams(node.params, constructor.valueParameters);
  }
}

class _KotlinGetterProcessor extends Visitor<Method, void> {
  final KotlinProperty getter;

  _KotlinGetterProcessor(this.getter);

  @override
  void visit(Method node) {
    node.returnType.accept(_KotlinTypeProcessor(getter.returnType));
  }
}

class _KotlinSetterProcessor extends Visitor<Method, void> {
  final KotlinProperty setter;

  _KotlinSetterProcessor(this.setter);

  @override
  void visit(Method node) {
    if (setter.setterParameter case final setterParam?) {
      node.params.single.type.accept(_KotlinTypeProcessor(setterParam.type));
    }
    node.params.single.type.accept(_KotlinTypeProcessor(setter.returnType));
  }
}

class _KotlinPropertyProcessor extends Visitor<Field, void> {
  final KotlinProperty property;

  _KotlinPropertyProcessor(this.property);

  @override
  void visit(Field node) {
    node.type.accept(_KotlinTypeProcessor(property.returnType));
  }
}

class _KotlinParamProcessor extends Visitor<Param, void> {
  final KotlinValueParameter kotlinParam;

  _KotlinParamProcessor(this.kotlinParam);

  @override
  void visit(Param node) {
    node.type.accept(_KotlinTypeProcessor(kotlinParam.type));
  }
}

class _KotlinTypeParamProcessor extends Visitor<TypeParam, void> {
  final KotlinTypeParameter kotlinTypeParam;

  _KotlinTypeParamProcessor(this.kotlinTypeParam);

  @override
  void visit(TypeParam node) {
    final kotlinBounds = kotlinTypeParam.upperBounds;
    final bounds = <String, KotlinType>{};
    for (final bound in kotlinBounds) {
      if (bound.name case final boundName?) {
        bounds[_toJavaBinaryName(boundName)] = bound;
      }
    }
    for (final bound in node.bounds) {
      if (bounds[bound.name] case final kotlinBound?) {
        bound.accept(_KotlinTypeProcessor(kotlinBound));
      }
    }
  }
}

class _KotlinTypeProcessor extends TypeVisitor<void> {
  final KotlinType kotlinType;

  _KotlinTypeProcessor(this.kotlinType);

  @override
  void visitDeclaredType(DeclaredType node) {
    for (var i = 0; i < node.params.length; ++i) {
      if (kotlinType.arguments[i] case final KotlinTypeProjection projection) {
        node.params[i].accept(_KotlinTypeProcessor(projection.type));
      }
    }
    super.visitDeclaredType(node);
  }

  @override
  void visitArrayType(ArrayType node) {
    if (kotlinType.arguments.isNotEmpty) {
      if (kotlinType.arguments.first
          case final KotlinTypeProjection projection) {
        node.elementType.accept(_KotlinTypeProcessor(projection.type));
      }
    }
    super.visitArrayType(node);
  }

  @override
  void visitWildcard(Wildcard node) {
    node.extendsBound?.accept(_KotlinTypeProcessor(kotlinType));
    node.superBound?.accept(_KotlinTypeProcessor(kotlinType));
    super.visitWildcard(node);
  }

  @override
  void visitNonPrimitiveType(ReferredType node) {
    node.annotations ??= [];
    node.annotations!
        .add(kotlinType.isNullable ? Annotation.nullable : Annotation.nonNull);
  }

  @override
  void visitPrimitiveType(PrimitiveType node) {
    // Do nothing.
  }
}
