'use strict';

// GLOBAL
const path = require('path');

// LOCAL
const tools = require('../../utils/tools');

// INNER MODULES
const innerGlobal = require('./global');
const innerPackages = require('./packages');

// PRIVATE FUNCTIONS
const getProjectMetadataDefs = (projectName) => {
  return {
    devopsMetadataFile: `app-${projectName}-build-metadata.json`,
    devopsEnvsMetadataFile: `app-${projectName}-envs-metadata.json`,
    devopsVersionsMetadataFile: `app-${projectName}-versions-metadata.json`,
    devopsHistoryMetadataFile: `app-${projectName}-history-metadata.json`,
  };
};

const getProjectOptions = (prj) => {
  let options = {
    BUILD_VERSION_STRATEGY: 'DEFAULT',
    BUILD_VERSION_STRATEGY_ENVS_CYCLE: 'DEFAULT',
  };

  if (prj.build) {
    if (prj.build.versionStrategy && prj.build.versionStrategy.envsCycle) {
      options.BUILD_VERSION_STRATEGY_ENVS_CYCLE = prj.build.versionStrategy.envsCycle;
    }
  }
  return { options: options };
};

const getProjectPaths = (prj) => {
  const rootPath = path.join(process.cwd(), prj.folder);
  let angularPath = rootPath;
  if (prj.build && prj.build.maven) {
    angularPath = path.join(rootPath, 'src/main/angular');
  }
  const assetsPath = path.join(angularPath, 'src', 'assets');
  const elementsPath = path.join(angularPath, 'src', 'assets', 'elements');
  const distPath = path.join(angularPath, 'dist');

  let installPath = process.cwd();
  let nodeModulesPath = path.join(process.cwd(), 'node_modules');
  if (prj.standalone && !prj.host) {
    installPath = path.join(rootPath);
    nodeModulesPath = path.join(rootPath, 'node_modules');
  }

  const paths = {
    rootPath: rootPath,
    angularPath: angularPath,
    elementsPath: elementsPath,
    installPath: installPath,
    nodeModulesPath: nodeModulesPath,
    assetsPath: assetsPath,
    distPath: distPath,
  };

  // locate and find the TSLint or ESLint configuration files
  if (tools.isFileExists(path.join(rootPath, 'src', 'tslint.json'))) {
    paths.tslintPath = path.join(rootPath, 'src', 'tslint.json');
  } else if (tools.isFileExists(path.join(rootPath, '.tslint.json'))) {
    paths.tslintPath = path.join(rootPath, '.tslint.json');
  } else if (tools.isFileExists(path.join(rootPath, 'src', '.eslintrc.json'))) {
    paths.eslintPath = path.join(rootPath, 'src', '.eslintrc.json');
  } else if (tools.isFileExists(path.join(rootPath, '.eslintrc.json'))) {
    paths.eslintPath = path.join(rootPath, '.eslintrc.json');
  } else if (tools.isFileExists(path.join(rootPath, 'src', 'eslint.config.mjs'))) {
    paths.eslintPath = path.join(rootPath, 'src', 'eslint.config.mjs');
  } else if (tools.isFileExists(path.join(rootPath, 'eslint.config.mjs'))) {
    paths.eslintPath = path.join(rootPath, 'eslint.config.mjs');
  }

  return { paths: paths };
};

module.exports.getProject = (projectName) => {
  const { root, project } = tools.getArgs();

  if (!projectName && !project) {
    projectName = root || 'app';
  } else if (project && !projectName) {
    projectName = project;
  }

  const config = innerGlobal.getConfig();

  if (!config.projects[projectName]) {
    return null;
  }

  const prj = config.projects[projectName];

  if (!prj) {
    throw 'PROJECT_NOT_FOUND';
  }

  if (prj) {
    prj.rootName = projectName;
    prj.csdr = true;
    prj.standalone = false;

    let prjVirtualSkeleton = {};

    if (prj.virtual && !innerGlobal.isCsdr()) {
      const { virtualProjectConfig } = require('./config-skeletons');
      prjVirtualSkeleton = virtualProjectConfig;

      prj.csdr = false;
      prj.standalone = true;

      prjVirtualSkeleton.build.translationScopes = prj.scopes;
      prjVirtualSkeleton.mock.npmPkg = prj.hostPackage;
      prjVirtualSkeleton.config.npmPkg = prj.hostPackage;
      prjVirtualSkeleton.externalSources[0].npmPkg = prj.hostPackage;
      prjVirtualSkeleton.externalRootFiles[0].npmPkg = prj.hostPackage;
      prjVirtualSkeleton.externalRootFiles[1].npmPkg = prj.hostPackage;
      prjVirtualSkeleton.externalRoutesSources.routesConfigNpmPkg = prj.hostPackage;

      if (prj.playground) {
        prjVirtualSkeleton.externalRootFiles[1].folder = 'app-root-playground';
      } else {
        prjVirtualSkeleton.externalRoutesSources.routesFilenameTemplate = 'route-defs.@env.target@.json';
      }
    }

    return {
      ...prj,
      ...prjVirtualSkeleton,
      ...getProjectPaths(prj),
      ...getProjectMetadataDefs(projectName),
      ...getProjectOptions(prj),
    };
  }
};

module.exports.getCsdrProject = (projectName) => {
  const prj = innerGlobal.getCsdrConfig(false).projects[projectName];

  if (prj) {
    prj.rootName = projectName;

    return {
      ...prj,
      ...getProjectPaths(prj),
      ...getProjectMetadataDefs(projectName),
      ...getProjectOptions(prj),
    };
  }
};

module.exports.getCsdrProjectsGroupForEuiVersion = (projectsGroupName, euiVersion) => {
  const prjGroup = innerGlobal.getCsdrConfig(false).projects[projectsGroupName];

  if (!prjGroup) {
    throw new Error('PROJECT_GROUP_NOT_FOUND');
  }

  tools.logInfo(`Project group found for : ${projectsGroupName} and eUI version : ${euiVersion}`);
  const prjGroupFromEuiVersion = prjGroup[euiVersion];
  if (!prjGroupFromEuiVersion) {
    throw new Error('PROJECT_GROUP_NOT_FOUND_FOR_EUI_VERSION');
  }

  console.log(prjGroupFromEuiVersion);
  return prjGroupFromEuiVersion;
};

const getProjects = (module.exports.getProjects = () => {
  const projects = innerGlobal.getConfig().projects;
  return Object.keys(projects).map((p) => this.getProject(p));
});

module.exports.getCsdrProjects = () => {
  const projects = [];

  const csdrProjects = innerGlobal.getCsdrConfig(false).projects;
  const csdrPackages = innerPackages.getCsdrPackages();

  Object.keys(csdrProjects).forEach((prj) => {
    const project = csdrProjects[prj];
    const teams = new Set();

    if (project.packages) {
      project.packages.forEach((p) => {
        const pkg = csdrPackages[p];

        if (!pkg) {
          console.log('...package not found: ' + p);
          return;
        }

        if (pkg.teams) {
          pkg.teams.forEach((team) => teams.add(team));
        }
      });
    }
    project.rootName = prj;
    project.teams = Array.from(teams);

    projects.push(project);
  });
  return projects;
};

module.exports.getTeamsProject = (projects, project) => {
  let teams = [];

  projects.forEach((p) => {
    if (p.name === project) {
      teams = p.teams;
    }
  });

  return teams;
};

module.exports.getBaseHref = (prj, version, providedBaseHref) => {
  tools.logInfo('Contructing baseHref :');
  tools.logInfo('provided args : ');
  console.log(version, providedBaseHref);

  if (providedBaseHref) {
    tools.logInfo(`---> provided baseHref: ${providedBaseHref}`);
    return providedBaseHref;
  }

  if (prj.build) {
    if (prj.build.baseHref) {
      tools.logInfo(`---> prj.build.baseHref: ${prj.build.baseHref}`);
      return prj.build.baseHref;
    } else {
      if (prj.build.distribution) {
        const distOptions = prj.build.distribution;

        if (distOptions.dynamicBaseHref && distOptions.folder) {
          let baseHref = distOptions.folder;
          if (distOptions.includeMajorVersion && version) {
            baseHref = '/' + baseHref + '-' + version.split('.')[0] + '.x' + '/';
            tools.logInfo(`---> distribution and includeMajorVersion and version found: ${baseHref}`);
          } else {
            if (distOptions.folder === '/') {
              baseHref = '/';
              tools.logInfo(`---> distribution folder is '/': ${baseHref}`);
            } else {
              tools.logInfo(`---> distribution folder is not '/': ${baseHref}`);
              baseHref = '/' + baseHref + '/';
            }
          }

          return baseHref;
        } else {
          tools.logInfo(`---> ${baseHref}`);
          return null;
        }
      }
    }
  }

  return null;
};

module.exports.getServePath = (prj, version, providedServePath) => {
  tools.logInfo('Constructing servePath:');
  tools.logInfo('provided args: ');
  console.log(version, providedServePath);

  if (providedServePath) {
    tools.logInfo(`---> provided servePath: ${providedServePath}`);
    return providedServePath;
  }

  return null;
};

const getEuiVersionCore = (project) => {
  let version;

  tools.logInfo(`Checking project dependencies in : ${project.folder}`);
  const depsCompositeFile = path.join(project.folder, 'dependencies-composite.json');
  const depsBaseFile = path.join(project.folder, 'dependencies-base.json');

  if (!tools.isFileExists(depsCompositeFile) || !tools.isFileExists(depsBaseFile)) {
    tools.logWarning('Unable to find project version / dependencies-composite.json does not exist in project');
  } else {
    tools.logInfo(`parsing ${depsCompositeFile} and ${depsBaseFile}`);
    const jsonFileContent = JSON.parse(tools.getFileContent(depsCompositeFile));
    const jsonFileContentBase = JSON.parse(tools.getFileContent(depsBaseFile));
    const depsComposite = jsonFileContent.dependencies;
    const depsBase = jsonFileContentBase;

    const deps = {...depsComposite, ...depsBase};

    if (!deps) {
      version = 'DEFAULT';
    } else {
      const euiDepsBase = deps['@eui/deps-base'];

      if (euiDepsBase) {
        let euiVersion = euiDepsBase.split('.')[0];

        if (euiVersion.substr(0, 1) === '^') {
          euiVersion = euiVersion.substr(1);
        }
        version = `${euiVersion}.x`;

        if (version === '7.x') {
          version = 'DEFAULT';
        }
      }
    }
  }

  return version;
};

module.exports.getProjectEuiVersion = (project) => {
  const version = getEuiVersionCore(project);

  if (version) {
    tools.logInfo(`checking ${project.name} => version found : ${version}\n`);
  } else {
    tools.logInfo(`checking ${project.name} => version detection skipped`);
  }

  return version;
};

module.exports.getLocalProjectsEuiVersion = () => {
  tools.logInfo('Getting local projects installed eUI version...');

  const prjs = getProjects();
  let versionsFound = [];

  prjs.forEach((p) => {
    let version = 'DEFAULT';

    if (p.build && p.build.euiVersion) {
      version = p.build.euiVersion;
    } else {
      version = this.getProjectEuiVersion(p);
    }

    versionsFound.push(version);
  });

  versionsFound = tools.removeArrayDuplicates(versionsFound);

  return versionsFound;
};
