import file from './io/file';
import connection from './networking/connection';
import connection_pool from './networking/connection_pool';
import * as ops from './ops';

export const connect = async (host_or_ip, port, password) => {
  const conn = new connection(host_or_ip, port, password);
  await conn.connect();
  return conn;
};

export const create_api = (conn) => {
  return {
    directory: {
      create: async (remote_path) => ops.create_directory(conn, remote_path),
      exists: async (remote_path) => {
        try {
          const info = await ops.get_file_attributes2(conn, remote_path);
          return info.directory;
        } catch (e) {
          if (e.message.split(':')[1].trim() == '-2') {
            return false;
          }
          throw new Error(e.message);
        }
      },
      list: async (remote_path, page_reader_cb) =>
        ops.list_directory(conn, remote_path, page_reader_cb),
      remove: async (remote_path) => ops.remove_directory(conn, remote_path),
      snapshot: async (remote_path) => {
        return ops.snapshot_directory(conn, remote_path);
      },
    },
    file: {
      create_or_open: async (remote_path) =>
        new file(
          conn,
          await ops.create_or_open_file(conn, remote_path),
          remote_path
        ),
      delete: async (remote_path) => ops.delete_file(conn, remote_path),
      download: async (
        remote_path,
        local_path,
        progress_cb,
        overwrite,
        resume
      ) =>
        ops.download_file(
          conn,
          remote_path,
          local_path,
          progress_cb,
          overwrite,
          resume
        ),
      exists: async (remote_path) => {
        try {
          const info = await ops.get_file_attributes2(conn, remote_path);
          return !info.directory;
        } catch (e) {
          if (e.message.split(':')[1].trim() == '-2') {
            return false;
          }
          throw new Error(e.message);
        }
      },
      open: async (remote_path) =>
        new file(conn, await ops.open_file(conn, remote_path), remote_path),
      upload: async (local_path, remote_path, progress_cb, overwrite, resume) =>
        ops.upload_file(
          conn,
          local_path,
          remote_path,
          progress_cb,
          overwrite,
          resume
        ),
    },
    get_drive_information: async () => ops.get_drive_information(conn),
  };
};

export const create_pool = async (pool_size, host_or_ip, port, password) => {
  if (pool_size <= 1) {
    return connect(host_or_ip, port, password);
  }

  return new connection_pool(pool_size, host_or_ip, port, password);
};
