import * as TE from 'fp-ts/TaskEither';
import {DocumentData} from '../../server/db/MongoServerDao';
import {MongoServerDao} from '../../server/db/MongoServerDao';
import {Program} from '../../program/Program';
import {ServerSideQuote} from '../../server/quote/ServerSideQuote';
import {Session} from '../../server/request/Session';
import {UserSession} from '../../server/request/UserSession';
import {initNewDocument} from '../../server/quote/loader';
import {pipe} from 'fp-ts/function';

type QuoteMaker = (program: Program) => (id: number) => ServerSideQuote;

export type AsyncQuoteFactory = (
  dao: MongoServerDao
) => (
  quote_maker: QuoteMaker
) => (
  program: Program
) => (session: Session) => (doc_data: DocumentData) => any;

/**
 * Create and init a new quote/document
 *
 * @param dao         - mongo dao
 * @param quote_maker - logic for how to create quote
 * @param session     - user session
 * @param doc_data    - preliminary data to load onto the document
 * @param program     - relevant program
 *
 * @return a quote
 */
export const quote_factory = (dao: MongoServerDao) => (
  quote_maker: QuoteMaker
) => (program: Program) => (session: Session) => (
  doc_data: DocumentData
): Promise<ServerSideQuote> =>
  pipe(
    initNewDocument(dao)(quote_maker(program))(program)(<UserSession>session)(
      doc_data
    ),
    TE.getOrElse(e => {
      throw e;
    })
  )();
