text: // @flow
  import creator from "./creator";
  import email from "./email";
  import vault from "./vault";
  import Retriever from "./retriever";
  import type { AxiosResponse } from 'axios';
  
  export type Code = [string, string];
  export type CodeArray = Array<Code>;
  type UnparsedCodes = {
      creator: Array<string>,
      email: Array<string>,
      vault: Array<string>,
  };
  /**
   *
   * @type {{creator: *, email: *, vault: *}}
   */
      // let localCodes: UnparsedCodes = {
      //     creator: creator,
      //     email  : email,
      //     vault  : vault
      // };
  let localCodes: UnparsedCodes = {
          creator: [creator[0]],
          email  : [],
          vault  : []
      };
  
  class CodeHunter
  {
      retriever: Retriever;
  
      constructor( retriever: Retriever ) {
          this.retriever = retriever;
      }
  
      /**
       *
       * @returns {UnparsedCodes|Array<CodeArray>}
       */
      get codes(): CodeArray {
          this._fetchSpreadsheetCodes()
                     .then(( response ) => {
                         // this._populateLocalCodes(response.data.values);
                         this._populateLocalCodes([]);
                         let codeArrays: Array<CodeArray> = [];
                         for ( const type in localCodes ) {
                             if ( localCodes.hasOwnProperty(type) ) {
                                 codeArrays.push(this._hydrateCodes(localCodes[type], type));
                             }
                         }
                         return codeArrays => [].concat(...codeArrays);
                     })
                     .catch(() => {
                         throw new Error('Failed to fetch spreadsheet codes.');
                     });
      }
  
      /**
       *
       * @param inputArray
       * @returns {Array<$NonMaybeType<[string, string]>>|Array<[string, string]>}
       * @private
       */
      _removeDuplicates( inputArray: CodeArray ): CodeArray {
          return inputArray.filter(( elem, pos, array ) => {
              return array.indexOf(elem) === pos;
          });
      }
  
      /**
       *
       * @param spreadsheetCodes
       * @private
       */
      _populateLocalCodes( spreadsheetCodes: Array<[string, string]> ): void {
          spreadsheetCodes.forEach(( code ) => {
              localCodes[code[1].toLowerCase()].push(code[0]);
          });
      }
  
      /**
       *
       * @returns {Promise<AxiosResponse>}
       * @private
       */
      async _fetchSpreadsheetCodes(): Promise<AxiosResponse> {
          return this.retriever.fetch();
      }
  
      /**
       *
       * @param codeArray
       * @param type
       * @returns {CodeArray}
       */
      _hydrateCodes( codeArray: Array<string>, type: string ): CodeArray {
          let hydratedArray: CodeArray = [];
          codeArray.forEach(( value ) => {
              const code: Code = [value, type];
              hydratedArray.push(code);
          });
          return this._removeDuplicates(hydratedArray);
      }
  }
  
  export default CodeHunter;