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

export * as byte_order from './utils/byte_order';
export { getCustomEncryption, setCustomEncryption } from './utils/constants';
export { default as packet } from './networking/packet';

export const connect = async (host_or_ip, port, password) => {
  const conn = new connection(host_or_ip, port, password);
  try {
    await conn.connect();
  } catch (e) {
    await conn.disconnect();
    throw e;
  }

  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
        ),
      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),
      remove: async (remote_path) => ops.remove_file(conn, 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 = async (host_or_ip, port, password) => {
  return connect(host_or_ip, port, password);
};
