export interface InquiryEvent {
  readonly type: string;
}

export namespace InquiryEvent {
  /**
   * Triggered when an Inquiry session has been created in the client.
   *
   * Dynamic Flow Templates will send this event at the same time as 'ready', and it will not
   * indicate user interaction.
   */
  export class Start implements InquiryEvent {
    readonly type: string = 'start';
    readonly inquiryId: string;
    readonly sessionToken: string;

    constructor(inquiryId: string, sessionToken: string) {
      this.inquiryId = inquiryId;
      this.sessionToken = sessionToken;
    }
  }

  /**
   * The current page in the Inquiry flow changed. This is primarily used with the Inlined React
   * flow to dynamically resize the widget based on the contents of the current page.
   *
   * page-change events receive a metadata object containing the following fields:
   *
   * @param name name of the next step as configured in the Inquiry Template
   * @param path string representing the step type
   */
  export class PageChange implements InquiryEvent {
    readonly type: string = 'page_change';
    readonly name: string;
    readonly path: string;

    constructor(name: string, path: string) {
      this.name = name;
      this.path = path;
    }
  }

  const isStart = (event: any): event is Start => {
    return (
      event != null &&
      typeof event === 'object' &&
      event.type === 'start' &&
      event.inquiryId !== undefined &&
      event.sessionToken !== undefined
    );
  };

  const isPageChange = (event: any): event is PageChange => {
    return (
      event != null &&
      typeof event === 'object' &&
      event.type === 'page_change' &&
      event.name !== undefined &&
      event.path !== undefined
    );
  };

  export const fromJson = (eventJson: any): InquiryEvent | null => {
    let event: InquiryEvent | null;

    if (isStart(eventJson)) {
      event = new Start(eventJson.inquiryId, eventJson.sessionToken);
    } else if (isPageChange(eventJson)) {
      event = new PageChange(eventJson.name, eventJson.path);
    } else {
      event = null;
    }

    return event;
  };
}
