text: // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  // SPDX-License-Identifier: Apache-2.0
  
  const {
    Environment,
    IotStatus,
    StateData,
    AnalysisError,
  } = require('core-lib');
  
  const StatePrepareAnalysis = require('./states/prepare-analysis');
  const StateCollectAnalysisResults = require('./states/collect-analysis-results');
  const StateJobCompleted = require('./states/job-completed');
  
  const REQUIRED_ENVS = [
    'ENV_SOLUTION_ID',
    'ENV_RESOURCE_PREFIX',
    'ENV_IOT_HOST',
    'ENV_IOT_TOPIC',
    'ENV_PROXY_BUCKET',
    'ENV_SNS_TOPIC_ARN',
    'ENV_DEFAULT_AI_OPTIONS',
    'ENV_DEFAULT_MINCONFIDENCE',
  ];
  
  exports.handler = async (event, context) => {
    console.log(`event = ${JSON.stringify(event, null, 2)}; context = ${JSON.stringify(context, null, 2)};`);
    try {
      const missing = REQUIRED_ENVS.filter(x => process.env[x] === undefined);
      if (missing.length) {
        throw new AnalysisError(`missing enviroment variables, ${missing.join(', ')}`);
      }
      /* merge Parallel state outputs */
      const merged = event;
      if (merged.parallelStateOutputs) {
        const parallelStateOutputs = merged.parallelStateOutputs.slice(0);
        delete merged.parallelStateOutputs;
        while (parallelStateOutputs.length) {
          const data = parallelStateOutputs.shift();
          if (!data.ExecutionArn) {
            merged.uuid = data.uuid;
            merged.input = {
              ...merged.input,
              ...data.input,
            };
            merged.data = {
              ...merged.data,
              ...data.data,
            };
          } else if (data.Output) {
            const output = JSON.parse(data.Output);
            merged.uuid = output.uuid;
            merged.input = {
              ...merged.input,
              ...output.input,
            };
            merged.data = {
              ...merged.data,
              ...output.data,
            };
          }
        }
      }
  
      /* state switching */
      const stateData = new StateData(Environment.StateMachines.Analysis, merged, context);
      let instance;
      switch (merged.operation) {
        case StateData.States.PrepareAnalysis:
          instance = new StatePrepareAnalysis(stateData);
          break;
        case StateData.States.CollectAnalysisResults:
          instance = new StateCollectAnalysisResults(stateData);
          break;
        case StateData.States.JobCompleted:
          instance = new StateJobCompleted(stateData);
          break;
        default:
          break;
      }
      if (!instance) {
        throw new AnalysisError(`${event.operation} not supported`);
      }
      await instance.process();
      await IotStatus.publish(stateData.miniJSON());
      return stateData.toJSON();
    } catch (e) {
      console.error(e);
      throw e;
    }
  };
  