// Slack
import { transformSlackToGeneric } from './channels/slack/toGeneric';
import { transformGenericToSlack } from './channels/slack/fromGeneric';
import { methodsSlackToGenrric } from './channels/slack/toGeneric/methods';
import { methodsGenrricToSlack } from './channels/slack/fromGeneric/methods';
import { parseSlackMrkdwnToMarkdown } from './channels/slack/parsers/parse-slack-mrkdwn-to-markdown';

// Salesforce
import { transformSalesforceToGeneric } from './channels/salesforce/toGeneric';
import { transformGenericToSalesforce } from './channels/salesforce/fromGeneric';

// ServiceNow
import { transformServiceNowToGeneric } from './channels/servicenow/toGeneric';
import { transformGenericToServiceNow } from './channels/servicenow/fromGeneric';

// RWC (v4)
import { transformRWCv4ToGeneric } from './channels/rwc/toGeneric';
import { transformGenericToRWCv4 } from './channels/rwc/fromGeneric';

// RWC (v5)
import { transformRWCv5ToGeneric } from './channels/rwc/toGeneric';
import { transformGenericToRWCv5 } from './channels/rwc/fromGeneric';

// RWC v6 uses the same structure as RWC v5
const transformRWCv6ToGeneric = transformRWCv5ToGeneric;
const transformGenericToRWCv6 = transformGenericToRWCv5;

// MS Dynamics
import { transformMSDynamicsToGeneric } from './channels/ms-dynamics/toGeneric';
import { transformGenericToMSDynamics } from './channels/ms-dynamics/fromGeneric';

// MS Teams
import { transformMSTeamsToGeneric } from './channels/ms-teams/toGeneric';
import { transformGenericToMSTeams } from './channels/ms-teams/fromGeneric';

// Zendesk
import { transformZendeskToGeneric } from './channels/zendesk/toGeneric';
import { transformGenericToZendesk } from './channels/zendesk/fromGeneric';

// SMS
import { transformSMSToGeneric } from './channels/sms/toGeneric';
import { transformGenericToSMS } from './channels/sms/fromGeneric';

// Nice CXone
import { transformNiceCxoneToGeneric } from './channels/nicecxone/toGeneric';
import { transformGenericToNiceCxone } from './channels/nicecxone/fromGeneric';

// Salesforce MIAW
import { transformSalesforceMiawToGeneric } from './channels/salesforce-miaw/toGeneric';
import { transformGenericToSalesforceMiaw } from './channels/salesforce-miaw/fromGeneric';

const Identity = (value) => value;

const toGenericFunctions = {
  generic: Identity,
  slack: transformSlackToGeneric,
  rwc: transformRWCv4ToGeneric,
  rwc_v5: transformRWCv5ToGeneric,
  rwc_v6: transformRWCv6ToGeneric,
  servicenow: transformServiceNowToGeneric,
  salesforce: transformSalesforceToGeneric,
  msdynamics:  transformMSDynamicsToGeneric,
  msteams: transformMSTeamsToGeneric,
  zendesk: transformZendeskToGeneric,
  nicecxone: transformNiceCxoneToGeneric,
  sms: transformSMSToGeneric,
  'salesforce-miaw': transformSalesforceMiawToGeneric,
};

const fromGenericFunctions = {
  generic: Identity,
  slack: transformGenericToSlack,
  rwc: transformGenericToRWCv4,
  rwc_v5: transformGenericToRWCv5,
  rwc_v6: transformGenericToRWCv6,
  servicenow: transformGenericToServiceNow,
  salesforce: transformGenericToSalesforce,
  msdynamics: transformGenericToMSDynamics,
  msteams: transformGenericToMSTeams,
  zendesk: transformGenericToZendesk,
  nicecxone: transformGenericToNiceCxone,
  sms: transformGenericToSMS,
  'salesforce-miaw': transformGenericToSalesforceMiaw,
};

const transform = (source, target, data) => {
  if (source === target) return data;
  
  if (!toGenericFunctions[source]) 
    throw new Error(`Invalid source channel: ${source}`);
  
  if (!fromGenericFunctions[target]) 
    throw new Error(`Invalid target channel: ${target}`);
  
  if (Array.isArray(data)) {
    return data.reduce((acc, item) => {
      const translated = transform(source, target, item);
      if (Array.isArray(translated?.messages)) {
        if (Array.isArray(acc)) {
          return {
            messages: acc.concat(translated.messages)
          };
        }

        return {
          messages: acc.messages.concat(translated.messages)
        };
      }

      return acc.concat(translated);
    }, []);
  } 
  
  return fromGenericFunctions[target](toGenericFunctions[source](data));
};

const channels = Object.keys(toGenericFunctions);

export default {
  // supported channels
  channels,

  // Generic function
  transform,

  // Slack
  parseSlackMrkdwnToMarkdown,
  transformSlackToGeneric,
  transformGenericToSlack,
  methodsSlackToGenrric,
  methodsGenrricToSlack,

  // Salesforce
  transformSalesforceToGeneric,
  transformGenericToSalesforce,

  // ServiceNow
  transformServiceNowToGeneric,
  transformGenericToServiceNow,

  // RWC
  transformRWCv4ToGeneric,
  transformGenericToRWCv4,

  //RWCv5
  transformRWCv5ToGeneric,
  transformGenericToRWCv5,

  //RWCv6
  transformRWCv6ToGeneric,
  transformGenericToRWCv6,

  //MS Dynamics
  transformGenericToMSDynamics,
  transformMSDynamicsToGeneric,

  //MS Teams
  transformGenericToMSTeams,
  transformMSTeamsToGeneric,

  // Zendesk
  transformZendeskToGeneric,
  transformGenericToZendesk,

  // Nice CXone
  transformNiceCxoneToGeneric,
  transformGenericToNiceCxone,

  // SMS
  transformSMSToGeneric,
  transformGenericToSMS,

  // Salesforce MIAW
  transformSalesforceMiawToGeneric,
  transformGenericToSalesforceMiaw,
};

