// Shared types

export namespace DataBase {
  export type OpenedApp = {
    appId: string;
    workspaceId: string;
    repoPath: string;
  };

  export type Workspace = {
    id: number;
    location: string;
  };

  export function narrowWorkspace(workspace: any): workspace is DataBase.Workspace {
    let W = workspace;
    try {
      return !!(W && 
              (typeof(W.id) === "number") && 
              (typeof(W.location) === "string") 
            );
    } catch(err) {
      console.error("Failed to narrow workspace", err);
      return false;
    }
  }

  export function narrowWorkspaceArray(workspaces: any): workspaces is DataBase.Workspace[] {
    try {
      let result = true;
      if (!Array.isArray(workspaces)) {
        return false;
      }

      for (let workspace of workspaces) {
        result = result && narrowWorkspace(workspace);
        if (!result) {
          break;
        }
      }

      return result;
    } catch (err) {
      console.error("Failed to narrow workspace array", err);
      return false;
    }
  }
}

export namespace FileSystem {
  export type MobileDevice = {
    id: string;
    name: string;
    type: string;
  };
  
  export function narrowMobileDevice(raw: any): raw is MobileDevice {
    try {
      return (typeof raw.id === "string") &&
        (typeof raw.name === "string") &&
        (typeof raw.type === "string");
    } catch(err) {
      console.error("Failed to validate mobile device", err);
      return false;
    }
  }

  export function narrowMobileDeviceArray(raw: any): raw is MobileDevice[] {
    try {
      let result = true;
      for (let i = 0; i < raw.length; ++i) {
        result = result && narrowMobileDevice(raw[i]);
        if (!result) {
          break;
        }
      }
      return result;
    } catch(err) {
      console.error("Failed to validate mobile device", err);
      return false;
    }
  }

  export type LocalMobileBundle = {
    fullPath: string;
    timestamp: number;
  };
  export type Repo = {
    name: string;
    fullPath: string;
    gitRepo: string;
    appId: string;
    apptileServer: string;
    appconfigServer: string;
    isOpen: boolean;
    codePushBundles: {
      ios: Array<LocalMobileBundle>; 
      android: Array<LocalMobileBundle>;
    };
  };

  export function narrowRepo(raw: any): raw is Repo {
    let result = (typeof raw.name === "string") &&
      (typeof raw.fullPath === "string") &&
      ((typeof raw.gitRepo === "string") || (raw.gitRepo === null)) &&
      (typeof raw.appId === "string") &&
      (typeof raw.apptileServer === "string") && 
      (typeof raw.appconfigServer === "string") &&
      (typeof raw.isOpen === "boolean");

    for (let i = 0; i < raw.codePushBundles.ios.length; ++i) {
      const bundle = raw.codePushBundles.ios[i];
      result = result && (typeof bundle.fullPath === "string") && (typeof bundle.timestamp === "number");
      if (!result) break;
    }

    for (let i = 0; i < raw.codePushBundles.android.length; ++i) {
      const bundle = raw.codePushBundles.android[i];
      result = result && (typeof bundle.fullPath === "string") && (typeof bundle.timestamp === "number");
      if (!result) break;
    }

    return result;
  }

  export function narrowRepoArray(raw: any): raw is Repo[] {
    try {
      let result = true;
      for (let i = 0; i < raw.length; ++i) {
        result = result && narrowRepo(raw[i]);
        if (!result) {
          break;
        }
      }
      return result;
    } catch (err) {
      console.error("Validation error: ", err);
      return false;
    }
  }

  export type WorkspaceData = {
    id: number;
    sdkHash: string;
    location: string;
    repos: Repo[];
  };

  export function narrowWorkspaceData(raw: any): raw is WorkspaceData {
    try {
      let result = (typeof raw.id === "number") &&
        (typeof raw.sdkHash === "string") &&
        (typeof raw.location === "string") && 
        narrowRepoArray(raw.repos);

      return result;
    } catch (err) {
      console.error("Validation Error: ", err);
      return false;
    }
  }

  export function narrowWorkspaceDataArray(raw: any): raw is WorkspaceData[] {
    try {
      let result = true;
      for (let i = 0; i < raw.length; ++i) {
        result = result && narrowWorkspaceData(raw[i]);
        if (!result) {
          break;
        }
      }
      return result;
    } catch (err) {
      console.error("Validation Error: ", err);
      return false;
    }
  }
}
