import 'dart:async';
import 'dart:convert';
import 'dart:io';
//import 'package:flutter/services.dart' show rootBundle;

import 'package:dart_framework/platform/process.dart';
import 'package:dart_framework/model/app_data.dart';
import 'package:dart_framework/utils/system_util.dart';

enum SCMType { Svn, Git }

class AppDataManager {
  AppDataManager._privateConstructor();
  static final AppDataManager _instance = AppDataManager._privateConstructor();
  static AppDataManager get to => _instance;

  late SCMType _scm;
  late String _workspace;
  late String _relativeAssetPath;

  // Future<AppData> read(String relativeAssetPath) async {
  //   return AppData.fromJson(jsonDecode(
  //       await rootBundle.loadString('$relativeAssetPath/app_data.json')));
  // }

  Future<AppData> create(SCMType scm, String workspace,
      String relativeAssetPath, String name) async {
    _scm = scm;
    _workspace = workspace;
    _relativeAssetPath = relativeAssetPath;
    var c = Completer<AppData>();
    var appData = AppData();
    appData.name = name;
    appData.gitCount = await gitCount();
    appData.version = await getVersion();
    appData.buildDate = getBuildTime();
    if (_scm == SCMType.Git) {
      appData.gitHash = await getHash();
    }
    await createFile(jsonEncode(appData.toJson()));
    c.complete(appData);
    return c.future;
  }

  Future<int> gitCount() async {
    var shell = StringBuffer();
    shell.writeln('git rev-list --all HEAD --all --count');
    var process = await ProcessExecutor.start(shell, workspace: _workspace);
    await process.waitForExit();
    return dataFutrue(int.parse(process.stdoutArr.last));
  }

  Future<String> getVersion() async {
    var c = Completer<String>();
    var number = 0;
    var shell = StringBuffer();
    switch (_scm) {
      case SCMType.Svn:
        break;
      case SCMType.Git:
        shell.writeln('git rev-list --all HEAD --all --count');
        var process = await ProcessExecutor.start(shell, workspace: _workspace);
        await process.waitForExit();
        number = int.parse(process.stdoutArr.last);
        break;
    }

    var version = numberToVersion(number);
    print('#### Version: $version');
    c.complete(version);
    return c.future;
  }

  String numberToVersion(int number, {int masterVersion = 0}) {
    var arr = number.toString().split('');
    var length = arr.length;
    var ver = '';
    var versionList = <int>[];
    for (int i = 0; i < length; ++i) {
      if (i != 0 && i % 3 == 0) {
        versionList.add(int.parse(ver));
        ver = '';
      }
      ver = arr[length - (i + 1)].toString() + ver;
    }
    if (ver != '') versionList.add(int.parse(ver));

    ver = '';
    length = 3;
    var list = <String>['0', '0', '0'];
    for (int i = 0; i < length; ++i) {
      var versionValue = versionList.length <= i ? 0 : versionList[i];
      var versionStr = i == 2
          ? (versionValue + masterVersion).toString()
          : versionValue.toString();
      list[length - (i + 1)] = versionStr;
    }
    return list.join('.');
  }

  double versionToNumber(String version) {
    var value = version.replaceAll('.', '');
    return double.parse(value);
  }

  Future<String> getHash() async {
    var shell = StringBuffer();
    shell.writeln('git rev-parse HEAD');
    var process = await ProcessExecutor.start(shell, workspace: _workspace);
    await process.waitForExit();
    var hash = process.stdoutArr.last;
    print('#### Git Hash: $hash');
    return dataFutrue(hash);
  }

  String getBuildTime() {
    var date = DateTime.now().toString();
    date = date.substring(0, date.lastIndexOf('.'));
    print('#### Build Date: $date');
    return date;
  }

  Future createFile(String json) async {
    var c = Completer();
    var dir = Directory('$_workspace/$_relativeAssetPath');
    if (!dir.existsSync()) dir.createSync(recursive: true);
    var file = File('$_workspace/$_relativeAssetPath/app_data.json');
    await file.writeAsString(json);
    c.complete();
    return c.future;
  }
}
