import 'dart:io';
import 'dart:async';
import 'package:dart_framework/utils/system_util.dart';
import 'package:path/path.dart' as path;

enum FileType { none, file, directory, link }

class Path {
  static String get userPath {
    String path = '';
    if (Platform.isWindows) {
      path = Platform.environment['USERPROFILE'] as String;
    } else if (Platform.isMacOS || Platform.isLinux) {
      path = Platform.environment['HOME'] as String;
    }
    return path;
  }

  static String get dataPath {
    String path = userPath;
    if (Platform.isMacOS) {
      path = '$path/Library/$appIdendifier';
    } else if (Platform.isLinux) {
      path = '$path/.config/$appIdendifier';
    } else if (Platform.isWindows) {
      path = '$path/AppData/Local/$appIdendifier';
    }
    if (Platform.isWindows) path = path.replaceAll('/', '\\');
    return path;
  }

  static String? getParent(String path) {
    path = getNormal(path);
    var separator = '/';
    int index = path.lastIndexOf(separator);
    if (index == -1) {
      return null;
    } else {
      return path.substring(0, index);
    }
  }

  static String getName(String path) {
    path = getNormal(path);
    var parent = getParent(path);
    var separator = '/';
    return path.replaceAll('$parent$separator', '');
  }

  static String getNormal(String path) {
    return path.replaceAll('\\', '/');
  }

  //Remove last slush(/)
  static String getNormalizePath(String path) {
    var separator = Platform.isMacOS ? '/' : '\\';
    if (path.lastIndexOf(separator) == path.length - 1) {
      path = path.substring(0, path.lastIndexOf(separator));
    }
    return path;
  }

  static FileType getType(String path) {
    if (Directory(path).existsSync()) return FileType.directory;
    if (File(path).existsSync()) return FileType.file;
    return FileType.none;
  }

  static Future<bool> copy(String startPath, String destPath, bool isDir,
      {required List<String>? ignorePattern,
      required List<String>? ignoredList,
      bool isMove = false,
      bool isOverwrite = true}) async {
    var c = Completer<bool>();
    var result = true;
    if (ignorePattern != null) {
      for (var pattern in ignorePattern) {
        if (startPath.contains(pattern)) {
          if (ignoredList != null) ignoredList.add(startPath);
          c.complete(true);
          return c.future;
        }
      }
    }
    try {
      var name = Path.getName(startPath);
      var destChildPath = path.join(destPath, name);
      if (isDir) {
        var startDir = Directory(startPath);
        var destDir = Directory(destChildPath);
        if (!startDir.existsSync()) {
          throw ArgumentError('Start - $startPath is not exist');
        }
        if (!destDir.existsSync()) destDir.createSync(recursive: true);
        var files = startDir.listSync();
        for (var file in files) {
          if (file is File) {
            await copy(file.path, destDir.path, false,
                ignorePattern: ignorePattern,
                ignoredList: ignoredList,
                isMove: isMove,
                isOverwrite: isOverwrite);
          }
          if (file is Directory) {
            await copy(file.path, destDir.path, true,
                ignorePattern: ignorePattern,
                ignoredList: ignoredList,
                isMove: isMove,
                isOverwrite: isOverwrite);
          }
        }
      } else {
        var destDir = Directory(destPath);
        if (!destDir.existsSync()) destDir.createSync(recursive: true);
        print('File copy: $startPath --> $destChildPath');
        var file = File(startPath);
        var fileDest = File(destChildPath);
        if (fileDest.existsSync()) {
          await fileDest.delete();
        }
        await file.copy(destChildPath);
        if (isMove) {
          await file.delete(recursive: true);
        }
      }
    } on Exception {
      result = false;
    }
    c.complete(result);
    return c.future;
  }
}
