import * as plugins from './spark.plugins.js';
import { Spark } from './index.js';
import * as paths from './spark.paths.js';
import { logger } from './spark.logging.js';

export class SparkTaskManager {
  public sparkRef: Spark;
  public taskmanager: plugins.taskbuffer.TaskManager;

  // tasks
  public updateSpark: plugins.taskbuffer.Task;
  public updateHost: plugins.taskbuffer.Task;
  public updateServices: plugins.taskbuffer.Task;

  constructor(sparkRefArg: Spark) {
    this.sparkRef = sparkRefArg;
    this.taskmanager = new plugins.taskbuffer.TaskManager();

    // updateSpark
    this.updateSpark = new plugins.taskbuffer.Task({
      name: 'updateSpark',
      taskFunction: async () => {
        const smartupdateInstance = new plugins.smartupdate.SmartUpdate({
          npmRegistryUrl: 'https://registry.npmjs.org',
        });
        const shouldUpdate = await smartupdateInstance.check(
          this.sparkRef.sparkInfo.projectInfo.name,
          this.sparkRef.sparkInfo.projectInfo.version
        );
        if (shouldUpdate) {
          await this.stop();
          const smartshellInstance = new plugins.smartshell.Smartshell({
            executor: 'bash',
          });

          await smartshellInstance.exec(`cd / && npm upgrade -g && spark updatedaemon`);
          logger.log('info', 'Cooling off before restart...');
          await plugins.smartdelay.delayFor(5000);
          logger.log('ok', '######## Trying to exit / Restart expected... ########');
          process.exit(0);
        }
      },
    });

    this.updateHost = new plugins.taskbuffer.Task({
      name: 'updateHost',
      taskFunction: async () => {
        await this.stop();
        const smartshellInstance = new plugins.smartshell.Smartshell({
          executor: 'bash',
        });
        await smartshellInstance.exec(
          `apt-get update && apt-get upgrade -y --force-yes && apt-get autoremove -y --force-yes && apt-get autoclean -y --force-yes`
        );
        await this.start();
      },
    });

    /**
     * only being run when mode is cloudly
     */
    this.updateServices = new plugins.taskbuffer.Task({
      name: 'updateCloudly',
      taskFunction: async () => {
        logger.log('info', 'now running updateCloudly task');
        this.sparkRef.sparkUpdateManager.updateServices();
      },
    });
  }

  /**
   * start the taskmanager
   */
  public async start() {
    this.taskmanager.addAndScheduleTask(this.updateServices, '30 */2 * * * *');
    this.taskmanager.addAndScheduleTask(this.updateSpark, '0 * * * * *');
    this.taskmanager.addAndScheduleTask(this.updateHost, '0 0 0 * * *');
    this.taskmanager.start();
  }

  /**
   * stops the taskmanager
   */
  public async stop() {
    this.taskmanager.descheduleTask(this.updateSpark);
    this.taskmanager.descheduleTask(this.updateHost);
    this.taskmanager.descheduleTask(this.updateServices);
    this.taskmanager.stop();
  }
}
