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

// @dart = 2.8

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 '../globals.dart' as globals;
import '../project.dart';
import 'android_sdk.dart';
import 'gradle.dart';

/// An application package created from an already built Android APK.
class AndroidApk extends ApplicationPackage {
  AndroidApk({
    String id,
    @required this.file,
    @required this.versionCode,
    @required this.launchActivity,
  }) : assert(file != null),
       assert(launchActivity != null),
       super(id: id);

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

    String apptStdout;
    try {
      apptStdout = globals.processUtils.runSync(
        <String>[
          aaptPath,
          'dump',
          'xmltree',
          apk.path,
          'AndroidManifest.xml',
        ],
        throwOnError: true,
      ).stdout.trim();
    } on ProcessException catch (error) {
      globals.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;
    }

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

    return AndroidApk(
      id: data.packageName,
      file: apk,
      versionCode: int.tryParse(data.versionCode),
      launchActivity: '${data.packageName}/${data.launchableActivityName}',
    );
  }

  /// Path to the actual apk file.
  final File file;

  /// 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,
  }) async {
    File apkFile;

    if (androidProject.isUsingGradle && androidProject.isSupportedVersion) {
      apkFile = getApkDirectory(androidProject.parent).childFile('app.apk');
      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,
        );
      }
      // 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(), 'app.apk'));
    }

    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 XmlParserException 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.toString()}');
    }

    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 XmlElement xmlElement = node as XmlElement;
          final String name = xmlElement.getAttribute('android:name');
          if (name == 'android.intent.action.MAIN') {
            actionName = name;
          } else if (name == 'android.intent.category.LAUNCHER') {
            categoryName = name;
          }
        }
        if (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,
      file: apkFile,
      versionCode: null,
      launchActivity: launchActivity,
    );
  }

  @override
  File get packagesFile => file;

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


class _Entry {
  _Element parent;
  int level;
}

class _Element extends _Entry {
  _Element.fromLine(String line, _Element parent) {
    //      E: application (line=29)
    final List<String> parts = line.trimLeft().split(' ');
    name = parts[1];
    level = line.length - line.trimLeft().length;
    this.parent = parent;
    children = <_Entry>[];
  }

  List<_Entry> children;
  String name;

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

  _Attribute firstAttribute(String name) {
    return children.whereType<_Attribute>().firstWhere(
        (_Attribute e) => e.key.startsWith(name),
        orElse: () => null,
    );
  }

  _Element firstElement(String name) {
    return children.whereType<_Element>().firstWhere(
        (_Element e) => e.name.startsWith(name),
        orElse: () => null,
    );
  }

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

class _Attribute extends _Entry {
  _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('=');
    key = keyVal[0];
    value = keyVal[1];
    level = line.length - line.trimLeft().length;
    this.parent = parent;
  }

  String key;
  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 == null || 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');
      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)')) {
      logger.printError('Error running $packageName. Manifest versionCode invalid');
      return null;
    }
    final int versionCode = 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>>{};
    map['package'] = <String, String>{'name': packageName};
    map['version-code'] = <String, String>{'name': versionCode.toString()};
    map['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();
}
