"use strict";
// MOVED TO ops-common
// import * as path from "path";
// import { inject } from 'inversify';
// import { INTERFACES } from '@codiac.io/codiac-common';
// import { BetterConsoleLogger } from "@codiac.io/codiac-common/better-logger"
// import { IBetterLogger, LogLevel } from '@codiac.io/codiac-common/IBetterLogger';
// import { CodiacError } from "@codiac.io/codiac-common/contracts";
// import { CliExec, JsonUtils } from '@codiac.io/codiac-ops-common';
// import { INTERFACES_CLI } from './INTERFACES_CLI';
// import { IDockerConfig, RegistryCredentials, UsernamePassword } from './docker-config';
// import { DOCKER_CONSTANTS } from './docker-constants';
// /**
//  * Credentials store:
//  * @see https://docs.docker.com/engine/reference/commandline/cli/
//  * @see https://docs.docker.com/engine/reference/commandline/login/#credentials-store
//  *
//  *  **EITHER** docker is set to store creds in the docker config  by default `$HOME/.docker/config.json`, overridden by env var `DOCKER_CONFIG` )
//  *  
//  *  **OR** it stores them in an external creds store, declared in the docker config as the value of the property `credsStore`.
//  *  The value of the credsStore setting is the suffix of the creds store helper program, 
//  *  which MUST be cenventionally named as `"docker-credential-${suffix}"`.
//  *  these programs MUST support a `get`, `store`, and `delete` method.
//  *  (NOTE: logging in stores em, logging out deletes them).
//  * 
//  *  SO:  In this case, to get the login creds for docker, we need to:
//  * 
//  *  a) get the path to the docker config:   `path = 'echo $DOCKER_CONFIG' || '$HOME/.docker/config.json'` 
//  * 
//  *  b) load the docker config:  `let config = JSON.parse(load[path to config.json])`
//  * 
//  *  c) check if the `credHelpers` contains the registry url youre looking for, 
//  * 
//  *     if not, fall back to `credsStore` property,
//  * 
//  *     if not, fall back to `auths` property which contains the creds for each registry
//  * 
//  *  d) if theres a credsStore or credHelpers, 
//  * 
//  *     1) Assemble the name of the binary: `let binary = 'docker-crenential-${credsStoreValue}';`
//  * 
//  *     2) fire the get command:  `let credsJson = spawnAndLog('${binary} get ${registry}')`
//  * 
//  *        NOTE:  there may be a "list" command, like there is for the "desktop" store.
//  *        if these creds arent there we have to throw 401 (missing or invalid creds),
//  *        and the CLI needs to recognize that missing creds error type so that it can prompt for creds.
//  *        and it should continue to loop a prompt while receiving a 401 invalid creds response (tho its called unauthorized).
//  *  
//  *  Q: Shall we throw on an unauthorized response (403)?  Or prompt them for creds again?  
//  */
// export class DockerCredentialsStore {
//   /** The fully qualified pathname of the docker config file that the docker runtime is using. */
//   public static configPath: string = DockerCredentialsStore.getConfigPath();
//   /** Factory method that determines which creds store docker is configured for 
//    * and spins up an instance with a matching configuration.  */
//   public static create(): DockerCredentialsStore {
//     try {
//       let config = this.loadDockerConfig();
//       // TODO:  Get the logger from the CLI's IOC container.
//       let logger = new BetterConsoleLogger();
//       let instance = new DockerCredentialsStore(config, new CliExec(logger), logger);
//       return instance;
//     } catch (err) {
//       throw err;
//     }
//   }
//   /** Determines the fully qualified pathname of the docker config file that the docker runtime is using. */
//   private static getConfigPath(): string {
//     let homePath = (process.platform === "win32") ? process.env["HOMEPATH"]! : process.env["HOME"]!;
//     let override = process.env[DOCKER_CONSTANTS.CONFIG_PATH_ENV_VAR_NAME];
//     return override || path.posix.join(homePath, DOCKER_CONSTANTS.DEFAULT_CONFIG_FOLDER, DOCKER_CONSTANTS.DEFAULT_CONFIG_FILE)
//   }
//   private static loadDockerConfig(): IDockerConfig {
//     try {
//       let config = JsonUtils.deserializeJsonFile<IDockerConfig>(this.configPath);
//       if (!config) throw new CodiacError(`Docker config file does not exist at [${this.configPath}].`)
//       return config;
//     } catch (err) {
//       throw err;
//     }
//   }
//   // -------------------------------------------------------------------------------------
//   //  NOTE:  Below is a help output from running: $ docker-credential-desktop --help
//   //         Do ALL cred helpers have these methods?  
//   //         (the Docker docs suggest the helper interface only requires store, get, and erase).
//   //  
//   //    erase       Removes a set of credentials from the store
//   //    get         Retrieves credentials from the store
//   //    help        Help about any command
//   //    list        Lists the credentials in the store
//   //    move        Move credentials from one store to another
//   //    store       Adds a set of credentials to the store
//   //    version     Display the version of the credentials helper protocol
//   // -------------------------------------------------------------------------------------
//   /** Use the static factory method DockerCredentialsStore.create() instead.  */
//   private constructor(@inject(INTERFACES_CLI.IDockerConfig) public config: IDockerConfig
//     , @inject(CliExec) private _cliExec: CliExec
//     , @inject(INTERFACES.IBetterLogger) private logger: IBetterLogger) {
//   }
//   /** Adds a set of credentials to the store. */
//   public async store(creds: RegistryCredentials): Promise<void> {
//     return new Promise<void>(async (resolve, reject) => {
//       try {
//         throw new CodiacError("store() is not implemented");
//         // resolve();
//       } catch (err) {
//         reject(err);
//       }
//     });
//   }
//   private getCredsStoreNameFor(registry: string): string | undefined {
//     let store: string | undefined;
//     if (this.config.credHelpers && this.config.credHelpers[registry]) {
//       store = this.config.credHelpers[registry];
//     } else if (this.config.credsStore) {
//       store = this.config.credsStore;
//     }
//     return store;
//   }
//   /** Retrieves credentials from the store. 
//    * @param registry Domain name without any protocol or path.  (eg:  index.docker.io, or ourstuff.azurecr.io)
//    */
//   //  * @param scope scope prefix within the registry used as the prefix in the image name (eg: "letmeaskmydog" for the image "letmeaskmydog/toyhauler-base")
//   public async tryGet(registry: string): Promise<UsernamePassword | undefined> {
//     return new Promise<UsernamePassword | undefined>(async (resolve, reject) => {
//       let creds: RegistryCredentials | undefined;
//       try {
//         let store = this.getCredsStoreNameFor(registry);
//         if (store) {
//           creds = await this.getFromStoreBinary(store, registry);
//           // }
//           // if (this.config.credHelpers && this.config.credHelpers[registry]) {
//           //   store = this.config.credHelpers[registry];
//           //   creds = await this.getFromStoreBinary(store, registry);
//           // } else if (this.config.credsStore) {
//           //   store = this.config.credsStore;
//           //   creds = await this.getFromStoreBinary(store, registry);
//         } else {
//           store = DockerCredentialsStore.configPath;
//           if (this.config.auths) {
//             let userpass = this.config.auths[registry];
//             if (userpass) creds = { ServerURL: registry, ...userpass }
//           }
//         }
//         // if (!creds) throw new CodiacError(`No credentials exist for [${scope ? registry.concat("/", scope) : registry}] in [${store}].`);
//         if (!creds) throw new CodiacError(`No credentials exist for [${registry}] in [${store}].`);
//         resolve(creds);
//       } catch (err) {
//         this.logger.debug(`Error attempting to get creds for [${registry}].`, err);
//         resolve(undefined);
//       }
//     });
//   }
//   /** 
//    * @param storeName the unprefixed codename for the store (eg: "osxkeychain" or "desktop") 
//   */
//   private getFromStoreBinary(storeName: string, registry: string): Promise<RegistryCredentials | undefined> {
//     return new Promise<RegistryCredentials | undefined>(async (resolve, reject) => {
//       try {
//         let binaryName = DOCKER_CONSTANTS.CRED_HELPER_PREFIX.concat(storeName);
//         // NOTE:  Docker requires that the binary be in the path, so we shouldnt have to worry about the path.
//         // ALSO:  The registry has to be passed in via STDIN, thus the echo-pipe-$1 syntax below...
//         let cmd = `echo ${registry} | ${binaryName} get $1`
//         // let creds = await this._cliExec.execAsyncJson<RegistryCredentials>(cmd, { cwd: process.cwd() }, LogLevel.debug, true);
//         let json = await this._cliExec.execAsyncStdOut(cmd, { cwd: process.cwd() }, LogLevel.debug, true);
//         if (!json || json == "") throw new CodiacError(`Credentials not found in store [${storeName}]. Response: ${json}`);
//         let obj = JSON.parse(json);
//         let creds = <RegistryCredentials>obj;
//         resolve(creds);
//       } catch (err) {
//         reject(err);
//       }
//     });
//   }
//   /** Removes a set of credentials from the store. */
//   public async erase(username: string, registry: string, scope?: string): Promise<void> {
//     return new Promise<void>(async (resolve, reject) => {
//       try {
//         throw new CodiacError("erase() is not implemented");
//         // resolve();
//       } catch (err) {
//         reject(err);
//       }
//     });
//   }
//   /** Lists the credentials in the store. */
//   public async list(username?: string, registry?: string): Promise<RegistryCredentials[]> {
//     return new Promise<RegistryCredentials[]>(async (resolve, reject) => {
//       try {
//         let creds: RegistryCredentials[] = [];
//         // Gather up all the registries that are declared under creds helpers
//         if (this.config.credHelpers) {
//           for (let registryName in this.config.credHelpers) {
//             let store = this.config.credHelpers[registryName];
//             let helped = await this.getFromStoreBinary(store, registryName);
//             if (helped) creds.push(helped);
//           }
//         }
//         // Get all the creds in the main creds store
//         if (this.config.credsStore) {
//           let store = this.config.credsStore;
//           let binaryName = DOCKER_CONSTANTS.CRED_HELPER_PREFIX.concat(store);
//           let cmd = `${binaryName} list`;
//           let json = await this._cliExec.execAsyncStdOut(cmd, { cwd: process.cwd() }, LogLevel.debug, true);
//           if (json && json != "") {
//             this.logger.trace(`${binaryName} list results`, json);
//             let obj = JSON.parse(json);
//             let inStore: RegistryCredentials[] = [];;
//             for (let serverUrl in obj) {
//               let regCreds: RegistryCredentials = { ServerURL: serverUrl, Username: obj[serverUrl], Secret: "undefined" };
//               inStore.push(regCreds);
//             }
//             creds.push(...inStore);
//           }
//         }
//         // Get any creds stored directly in the config file
//         let store = DockerCredentialsStore.configPath;
//         if (this.config.auths) {
//           for (let registryName in this.config.auths) {
//             let userpass = this.config.auths[registryName];
//             if (userpass) creds.push({ ServerURL: registryName, ...userpass });
//           }
//         }
//         if (registry) {
//           creds = creds.filter(c => c.ServerURL == registry);
//         }
//         if (username) {
//           creds = creds.filter(c => c.Username == username);
//         }
//         // TODO: select distinct by registry
//         resolve(creds);
//       } catch (err) {
//         reject(err);
//       }
//     });
//   }
// }
//# sourceMappingURL=docker-credentials-store.js.map