text: const Config = require("truffle-config");
  const path = require("path");
  const fs = require("fs");
  
  class LoadingStrategy {
    constructor(options) {
      const defaultConfig = {
        compilerRoots: [
          "https://relay.trufflesuite.com/solc/bin/",
          "https://solc-bin.ethereum.org/bin/",
          "https://ethereum.github.io/solc-bin/bin/"
        ],
        dockerTagsUrl:
          "https://registry.hub.docker.com/v2/repositories/ethereum/solc/tags/"
      };
      this.config = Object.assign({}, defaultConfig, options);
  
      const compilersDir = path.resolve(
        Config.getTruffleDataDirectory(),
        "compilers"
      );
      const compilerCachePath = path.resolve(compilersDir, "node_modules"); // because babel binds to require & does weird things
      if (!fs.existsSync(compilersDir)) fs.mkdirSync(compilersDir);
      if (!fs.existsSync(compilerCachePath)) fs.mkdirSync(compilerCachePath); // for 5.0.8 users
  
      this.compilerCachePath = compilerCachePath;
    }
  
    addFileToCache(code, fileName) {
      const filePath = this.resolveCache(fileName);
      fs.writeFileSync(filePath, code);
    }
  
    errors(kind, input, error) {
      const info = "Run `truffle compile --list` to see available versions.";
  
      const kinds = {
        noPath: "Could not find compiler at: " + input,
        noVersion:
          `Could not find a compiler version matching ${input}. ` +
          `Please ensure you are specifying a valid version, constraint or ` +
          `build in the truffle config. ${info}`,
        noRequest:
          "Failed to complete request to: " +
          input +
          ". Are you connected to the internet?\n\n" +
          error,
        noUrl: "compiler root URL missing",
        noDocker:
          "You are trying to run dockerized solc, but docker is not installed.",
        noImage:
          "Please pull " +
          input +
          " from docker before trying to compile with it.",
        noNative: "Could not execute local solc binary: " + error,
        noString:
          "`compilers.solc.version` option must be a string specifying:\n" +
          "   - a path to a locally installed solcjs\n" +
          "   - a solc version or range (ex: '0.4.22' or '^0.5.0')\n" +
          "   - a docker image name (ex: 'stable')\n" +
          "   - 'native' to use natively installed solc\n" +
          "Received: " +
          input +
          " instead."
      };
  
      return new Error(kinds[kind]);
    }
  
    fileIsCached(fileName) {
      const file = this.resolveCache(fileName);
      return fs.existsSync(file);
    }
  
    load(_userSpecification) {
      throw new Error(
        "Abstract method LoadingStrategy.load is not implemented for this strategy."
      );
    }
  
    /**
     * Cleans up error listeners set (by solc?) when requiring it. (This code inherited from
     * previous implementation, note to self - ask Tim about this)
     */
    removeListener() {
      const listeners = process.listeners("uncaughtException");
      const execeptionHandler = listeners[listeners.length - 1];
  
      if (execeptionHandler) {
        process.removeListener("uncaughtException", execeptionHandler);
      }
    }
  
    resolveCache(fileName) {
      return path.resolve(this.compilerCachePath, fileName);
    }
  }
  
  module.exports = LoadingStrategy;
  