// ignore_for_file: depend_on_referenced_packages

import 'dart:core';
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:oto/oto/application.dart';
import 'package:oto/oto/commands/command.dart';
import 'package:oto/oto/data/command_data.dart';
import 'package:oto/oto/commands/ftp/ftp.dart';
import 'package:dart_framework/utils/path.dart';

class Upload extends Command {
  @override
  Future execute(DataCommand command) async {
    var data = DataFTP.fromJson(getParam(command));

    //Check asterisk
    var uploadMap = <String, String>{};
    var map = data.map;
    int port = data.port == 0 ? (data.sftp ? 22 : 21) : data.port;

    var ftp = data.sftp
        ? SFTP(data.host,
            port: port,
            user: data.user,
            password: data.password,
            runtime: runtime)
        : FTP(data.host, port: port, user: data.user, password: data.password);
    Application.log(
        '========================= [Try connection] =========================');
    await ftp.connect();
    Application.log(
        '========================= [Connected! Start Upload] ================');
    var entries = map.entries;
    for (var entry in entries) {
      var local = path.join(workspace, entry.key);
      var remote = entry.value;
      Application.log('[Upload]: $local ====> $remote');

      var parentRemote = Path.getParent(remote);
      var remoteMap = await ftp.list(parentRemote!);
      var parentLocal = Path.getParent(local);
      var nameLocal = Path.getName(local);

      if (nameLocal == '*') {
        // Wildcard (*): delete the remote folder first for a full replacement
        //Remove before folder
        if (remoteMap.containsKey(remote) &&
            remoteMap[remote] == FileType.directory) {
          await ftp.delete([remote]);
        }
        //Create new folder
        await ftp.createFolder(remote);
        var parentLocalDir = Directory(parentLocal!);
        if (parentLocalDir.existsSync()) {
          var localFiles = parentLocalDir.listSync();
          var map = <String, String>{};
          for (var file in localFiles) {
            map[file.path] = remote;
          }
          await ftp.upload(map);
        } else {
          throw ArgumentError('Start - $parentLocal is not exist');
        }
      } else {
        uploadMap[local] = remote;
      }
    }

    if (uploadMap.isNotEmpty) await ftp.upload(uploadMap);

    await ftp.disconnect();
    Application.log(
        '========================= [Upload completed!] ======================');
    return complete(0, command);
  }
}

void registerFtpUploadCommand() {
  Command.register(
    CommandType.Upload,
    () => Upload(),
    spec: const CommandSpec(
      type: CommandType.Upload,
      category: 'ftp',
      dataModel: 'DataFTP',
      samplePath: 'assets/yaml/sample/09_network.yaml',
    ),
  );
}
