// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:collection';

import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:xml/xml.dart';

import '../application_package.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/process.dart';
import '../base/user_messages.dart';
import '../build_info.dart';
import '../project.dart';
import 'android_sdk.dart';
import 'gradle.dart';

/// An application package created from an already built Android APK.
class AndroidApk extends ApplicationPackage implements PrebuiltApplicationPackage {
  AndroidApk({
    required super.id,
    required this.applicationPackage,
    required this.versionCode,
    required this.launchActivity,
  });

  /// Creates a new AndroidApk from an existing APK.
  ///
  /// Returns `null` if the APK was invalid or any required tooling was missing.
  static AndroidApk? fromApk(
    File apk, {
    required AndroidSdk androidSdk,
    required ProcessManager processManager,
    required UserMessages userMessages,
    required Logger logger,
    required ProcessUtils processUtils,
  }) {
    final String? aaptPath = androidSdk.latestVersion?.aaptPath;
    if (aaptPath == null || !processManager.canRun(aaptPath)) {
      logger.printError(userMessages.aaptNotFound);
      return null;
    }

    String apptStdout;
    try {
      apptStdout = processUtils.runSync(
        <String>[
          aaptPath,
          'dump',
          'xmltree',
          apk.path,
          'AndroidManifest.xml',
        ],
        throwOnError: true,
      ).stdout.trim();
    } on ProcessException catch (error) {
      logger.printError('Failed to extract manifest from APK: $error.');
      return null;
    }

    final ApkManifestData? data = ApkManifestData.parseFromXmlDump(apptStdout, logger);

    if (data == null) {
      logger.printError('Unable to read manifest info from ${apk.path}.');
      return null;
    }

    final String? packageName = data.packageName;
    if (packageName == null || data.launchableActivityName == null) {
      logger.printError('Unable to read manifest info from ${apk.path}.');
      return null;
    }

    return AndroidApk(
      id: packageName,
      applicationPackage: apk,
      versionCode: data.versionCode == null ? null : int.tryParse(data.versionCode!),
      launchActivity: '${data.packageName}/${data.launchableActivityName}',
    );
  }

  @override
  final FileSystemEntity applicationPackage;

  /// The path to the activity that should be launched.
  final String launchActivity;

  /// The version code of the APK.
  final int? versionCode;

  /// Creates a new AndroidApk based on the information in the Android manifest.
  static Future<AndroidApk?> fromAndroidProject(
    AndroidProject androidProject, {
    required AndroidSdk? androidSdk,
    required ProcessManager processManager,
    required UserMessages userMessages,
    required ProcessUtils processUtils,
    required Logger logger,
    required FileSystem fileSystem,
    BuildInfo? buildInfo,
  }) async {
    final File apkFile;
    final String filename;
    if (buildInfo == null) {
      filename = 'app.apk';
    } else if (buildInfo.flavor == null) {
      filename = 'app-${buildInfo.mode.name}.apk';
    } else {
      filename = 'app-${buildInfo.lowerCasedFlavor}-${buildInfo.mode.name}.apk';
    }

    if (androidProject.isUsingGradle && androidProject.isSupportedVersion) {
      Directory apkDirectory = getApkDirectory(androidProject.parent);
      if (androidProject.parent.isModule) {
        // Module builds output the apk in a subdirectory that corresponds
        // to the buildmode of the apk.
        apkDirectory = apkDirectory.childDirectory(buildInfo!.mode.name);
      }
      apkFile = apkDirectory.childFile(filename);
      if (apkFile.existsSync()) {
        // Grab information from the .apk. The gradle build script might alter
        // the application Id, so we need to look at what was actually built.
        return AndroidApk.fromApk(
          apkFile,
          androidSdk: androidSdk!,
          processManager: processManager,
          logger: logger,
          userMessages: userMessages,
          processUtils: processUtils,
        );
      }
      // The .apk hasn't been built yet, so we work with what we have. The run
      // command will grab a new AndroidApk after building, to get the updated
      // IDs.
    } else {
      apkFile = fileSystem.file(fileSystem.path.join(getAndroidBuildDirectory(), filename));
    }

    final File manifest = androidProject.appManifestFile;

    if (!manifest.existsSync()) {
      logger.printError('AndroidManifest.xml could not be found.');
      logger.printError('Please check ${manifest.path} for errors.');
      return null;
    }

    final String manifestString = manifest.readAsStringSync();
    XmlDocument document;
    try {
      document = XmlDocument.parse(manifestString);
    } on XmlException catch (exception) {
      String manifestLocation;
      if (androidProject.isUsingGradle) {
        manifestLocation = fileSystem.path.join(androidProject.hostAppGradleRoot.path, 'app', 'src', 'main', 'AndroidManifest.xml');
      } else {
        manifestLocation = fileSystem.path.join(androidProject.hostAppGradleRoot.path, 'AndroidManifest.xml');
      }
      logger.printError('AndroidManifest.xml is not a valid XML document.');
      logger.printError('Please check $manifestLocation for errors.');
      throwToolExit('XML Parser error message: $exception');
    }

    final Iterable<XmlElement> manifests = document.findElements('manifest');
    if (manifests.isEmpty) {
      logger.printError('AndroidManifest.xml has no manifest element.');
      logger.printError('Please check ${manifest.path} for errors.');
      return null;
    }
    final String? packageId = manifests.first.getAttribute('package');

    String? launchActivity;
    for (final XmlElement activity in document.findAllElements('activity')) {
      final String? enabled = activity.getAttribute('android:enabled');
      if (enabled != null && enabled == 'false') {
        continue;
      }

      for (final XmlElement element in activity.findElements('intent-filter')) {
        String? actionName = '';
        String? categoryName = '';
        for (final XmlNode node in element.children) {
          if (node is! XmlElement) {
            continue;
          }
          final String? name = node.getAttribute('android:name');
          if (name == 'android.intent.action.MAIN') {
            actionName = name;
          } else if (name == 'android.intent.category.LAUNCHER') {
            categoryName = name;
          }
        }
        if (actionName != null && categoryName != null && actionName.isNotEmpty && categoryName.isNotEmpty) {
          final String? activityName = activity.getAttribute('android:name');
          launchActivity = '$packageId/$activityName';
          break;
        }
      }
    }

    if (packageId == null || launchActivity == null) {
      logger.printError('package identifier or launch activity not found.');
      logger.printError('Please check ${manifest.path} for errors.');
      return null;
    }

    return AndroidApk(
      id: packageId,
      applicationPackage: apkFile,
      versionCode: null,
      launchActivity: launchActivity,
    );
  }

  @override
  String get name => applicationPackage.basename;
}

abstract class _Entry {
  const _Entry(this.parent, this.level);

  final _Element? parent;
  final int level;
}

class _Element extends _Entry {
  _Element._(this.name, _Element? parent, int level) : super(parent, level);

  factory _Element.fromLine(String line, _Element? parent) {
    //      E: application (line=29)
    final List<String> parts = line.trimLeft().split(' ');
    return _Element._(parts[1], parent, line.length - line.trimLeft().length);
  }

  final List<_Entry> children = <_Entry>[];
  final String? name;

  void addChild(_Entry child) {
    children.add(child);
  }

  _Attribute? firstAttribute(String name) {
    for (final _Attribute child in children.whereType<_Attribute>()) {
      if (child.key?.startsWith(name) ?? false) {
        return child;
      }
    }
    return null;
  }

  _Element? firstElement(String name) {
    for (final _Element child in children.whereType<_Element>()) {
      if (child.name?.startsWith(name) ?? false) {
        return child;
      }
    }
    return null;
  }

  Iterable<_Element> allElements(String name) {
    return children.whereType<_Element>().where((_Element e) => e.name?.startsWith(name) ?? false);
  }
}

class _Attribute extends _Entry {
  const _Attribute._(this.key, this.value, _Element? parent, int level) : super(parent, level);

  factory _Attribute.fromLine(String line, _Element parent) {
    //     A: android:label(0x01010001)="hello_world" (Raw: "hello_world")
    const String attributePrefix = 'A: ';
    final List<String> keyVal = line.substring(line.indexOf(attributePrefix) + attributePrefix.length).split('=');
    return _Attribute._(keyVal[0], keyVal[1], parent, line.length - line.trimLeft().length);
  }

  final String? key;
  final String? value;
}

class ApkManifestData {
  ApkManifestData._(this._data);

  static bool _isAttributeWithValuePresent(
      _Element baseElement, String childElement, String attributeName, String attributeValue) {
    final Iterable<_Element> allElements = baseElement.allElements(childElement);
    for (final _Element oneElement in allElements) {
      final String? elementAttributeValue = oneElement
          .firstAttribute(attributeName)
          ?.value;
      if (elementAttributeValue != null &&
          elementAttributeValue.startsWith(attributeValue)) {
        return true;
      }
    }
    return false;
  }

  static ApkManifestData? parseFromXmlDump(String data, Logger logger) {
    if (data.trim().isEmpty) {
      return null;
    }

    final List<String> lines = data.split('\n');
    assert(lines.length > 3);

    final int manifestLine = lines.indexWhere((String line) => line.contains('E: manifest'));
    final _Element manifest = _Element.fromLine(lines[manifestLine], null);
    _Element currentElement = manifest;

    for (final String line in lines.skip(manifestLine)) {
      final String trimLine = line.trimLeft();
      final int level = line.length - trimLine.length;

      // Handle level out
      while (currentElement.parent != null && level <= currentElement.level) {
        currentElement = currentElement.parent!;
      }

      if (level > currentElement.level) {
        switch (trimLine[0]) {
          case 'A':
            currentElement
                .addChild(_Attribute.fromLine(line, currentElement));
            break;
          case 'E':
            final _Element element = _Element.fromLine(line, currentElement);
            currentElement.addChild(element);
            currentElement = element;
        }
      }
    }

    final _Element? application = manifest.firstElement('application');
    if (application == null) {
      return null;
    }

    final Iterable<_Element> activities = application.allElements('activity');

    _Element? launchActivity;
    for (final _Element activity in activities) {
      final _Attribute? enabled = activity.firstAttribute('android:enabled');
      final Iterable<_Element> intentFilters = activity.allElements('intent-filter');
      final bool isEnabledByDefault = enabled == null;
      final bool isExplicitlyEnabled = enabled != null && (enabled.value?.contains('0xffffffff') ?? false);
      if (!(isEnabledByDefault || isExplicitlyEnabled)) {
        continue;
      }

      for (final _Element element in intentFilters) {
        final bool isMainAction = _isAttributeWithValuePresent(
            element, 'action', 'android:name', '"android.intent.action.MAIN"');
        if (!isMainAction) {
          continue;
        }
        final bool isLauncherCategory = _isAttributeWithValuePresent(
            element, 'category', 'android:name',
            '"android.intent.category.LAUNCHER"');
        if (!isLauncherCategory) {
          continue;
        }
        launchActivity = activity;
        break;
      }
      if (launchActivity != null) {
        break;
      }
    }

    final _Attribute? package = manifest.firstAttribute('package');
    // "io.flutter.examples.hello_world" (Raw: "io.flutter.examples.hello_world")
    final String? packageName = package?.value?.substring(1, package.value?.indexOf('" '));

    if (launchActivity == null) {
      logger.printError('Error running $packageName. Default activity not found');
      return null;
    }

    final _Attribute? nameAttribute = launchActivity.firstAttribute('android:name');
    // "io.flutter.examples.hello_world.MainActivity" (Raw: "io.flutter.examples.hello_world.MainActivity")
    final String? activityName = nameAttribute?.value?.substring(1, nameAttribute.value?.indexOf('" '));

    // Example format: (type 0x10)0x1
    final _Attribute? versionCodeAttr = manifest.firstAttribute('android:versionCode');
    if (versionCodeAttr == null) {
      logger.printError('Error running $packageName. Manifest versionCode not found');
      return null;
    }
    if (versionCodeAttr.value?.startsWith('(type 0x10)') != true) {
      logger.printError('Error running $packageName. Manifest versionCode invalid');
      return null;
    }
    final int? versionCode = versionCodeAttr.value == null ? null : int.tryParse(versionCodeAttr.value!.substring(11));
    if (versionCode == null) {
      logger.printError('Error running $packageName. Manifest versionCode invalid');
      return null;
    }

    final Map<String, Map<String, String>> map = <String, Map<String, String>>{
      if (packageName != null)
        'package': <String, String>{'name': packageName},
      'version-code': <String, String>{'name': versionCode.toString()},
      if (activityName != null)
        'launchable-activity': <String, String>{'name': activityName},
    };

    return ApkManifestData._(map);
  }

  final Map<String, Map<String, String>> _data;

  @visibleForTesting
  Map<String, Map<String, String>> get data =>
      UnmodifiableMapView<String, Map<String, String>>(_data);

  String? get packageName => _data['package'] == null ? null : _data['package']?['name'];

  String? get versionCode => _data['version-code'] == null ? null : _data['version-code']?['name'];

  String? get launchableActivityName {
    return _data['launchable-activity'] == null ? null : _data['launchable-activity']?['name'];
  }

  @override
  String toString() => _data.toString();
}
