// ets_tracing: off
import { Case } from "@effect-ts/core/Case";
import * as C from "@effect-ts/core/Collections/Immutable/Chunk";
import * as T from "@effect-ts/core/Effect";
import { not, pipe } from "@effect-ts/core/Function";
import * as O from "@effect-ts/core/Option";
import * as FigletClient from "../FigletClient/index.mjs";
import * as Fig from "../Figure/index.mjs";
import * as HL from "../RenderOptions/HorizontalLayout/index.mjs";
import { RenderOptions } from "../RenderOptions/index.mjs";
import * as J from "../RenderOptions/Justification/index.mjs";
import * as PD from "../RenderOptions/PrintDirection/index.mjs";
import * as Actions from "./BuilderAction/index.mjs"; // -----------------------------------------------------------------------------
// Model
// -----------------------------------------------------------------------------

/**
 * Represents a collection of rendering options.
 *
 * This builder works by recording what settings a user wants to use instead of
 * applying the setting immediately when calling a method. This allows for a
 * fail-safe behaviour when, for instance, a user wants to load a file but the
 * file is missing. Instead of receiving an exception when calling
 * `OptionsBuilder.withFont`, the builder will simply record the desire of to
 * load a file. The actual loading, and failure, will happen and be handled when
 * calling `OptionsBuilder.compile()`.
 */

export class OptionsBuilder {
  constructor(
  /**
   * The list of actions that will be executed to obtain the final
   * configuration.
   */
  actions = C.empty()) {
    this.actions = actions;
  }

}
export class BuildData extends Case {} // -----------------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------------

/**
 * Creates a new `OptionsBuilder` with default settings.
 */

export function builder() {
  return new OptionsBuilder();
}
/**
 * Creates a new `OptionsBuilder` with default settings and using an initial
 * action.
 */

export function withInitialAction(initialAction) {
  return new OptionsBuilder(C.single(initialAction));
}
/**
 * Create a new instance of `BuildData` using the provided parameters.
 */

export function buildData(params = {}) {
  return new BuildData({
    font: O.none,
    horizontalLayout: HL.FontDefault,
    justification: J.FontDefault,
    maxWidth: O.none,
    printDirection: PD.FontDefault,
    text: "",
    ...params
  });
} // -----------------------------------------------------------------------------
// Combinators
// -----------------------------------------------------------------------------

/**
 * Set the text to render.
 */

export function text_(self, text) {
  return addAction(self, new Actions.SetText({
    text
  }));
}
/**
 * Set the text to render.
 *
 * @ets_data_first text_
 */

export function text(text) {
  return self => text_(self, text);
}
/**
 * Use the default `FigFont` to render the text.
 */

export function withDefaultFont(self) {
  return addAction(self, new Actions.DefaultFont());
}
/**
 * Use one of the internal fonts to render the text.
 *
 * The loading of the font is performed when the `RenderOptions` is built.
 */

export function withInternalFont_(self, font) {
  return addAction(self, new Actions.LoadInternalFont({
    font
  }));
}
/**
 * Use one of the internal fonts to render the text.
 *
 * The loading of the font is performed when the `RenderOptions` is built.
 *
 * @ets_data_first withInternalFont_
 */

export function withInternalFont(font) {
  return self => withInternalFont_(self, font);
}
/**
 * Use a font loaded from a Figlet file to render the text.
 *
 * The loading of the font is performed when the `RenderOptions` is built.
 */

export function withFont_(self, fontPath) {
  return addAction(self, new Actions.LoadFont({
    fontPath
  }));
}
/**
 * Use a font loaded from a Figlet file to render the text.
 *
 * The loading of the font is performed when the `RenderOptions` is built.
 *
 * @ets_data_first withFont_
 */

export function withFont(fontPath) {
  return self => withFont_(self, fontPath);
}
/**
 * Use a font that has already been loaded to render the text.
 */

export function withFigFont_(self, font) {
  return addAction(self, new Actions.SetFont({
    font
  }));
}
/**
 * Use a font that has already been loaded to render the text.
 *
 * @ets_data_first withFigFont_
 */

export function withFigFont(font) {
  return self => withFigFont_(self, font);
}
/**
 * Use the default horizontal layout to render the text.
 */

export function withDefaultHorizontalLayout(self) {
  return addAction(self, new Actions.DefaultHorizontalLayout());
}
/**
 * Use the specified `HorizontalLayout` to render the text.
 */

export function withHorizontalLayout_(self, layout) {
  return addAction(self, new Actions.SetHorizontalLayout({
    layout
  }));
}
/**
 * Use the specified `HorizontalLayout` to render the text.
 *
 * @ets_data_first withHorizontalLayout_
 */

export function withHorizontalLayout(layout) {
  return self => withHorizontalLayout_(self, layout);
}
/**
 * Use the default maximum width to render the text.
 */

export function withDefaultMaxWidth(self) {
  return addAction(self, new Actions.DefaultMaxWidth());
}
/**
 * Use the specified maximum width to render the text.
 */

export function withMaxWidth_(self, maxWidth) {
  return addAction(self, new Actions.SetMaxWidth({
    maxWidth
  }));
}
/**
 * Use the specified maximum width to render the text.
 *
 * @ets_data_first withMaxWidth_
 */

export function withMaxWidth(maxWidth) {
  return self => withMaxWidth_(self, maxWidth);
}
/**
 * Use the default print direction to render the text.
 *
 * **NOTE**: This feature is not yet implemented and will have no effect.
 */

export function withDefaultPrintDirection(self) {
  return addAction(self, new Actions.DefaultPrintDirection());
}
/**
 * Use the specified print direction to render the text.
 *
 * **NOTE**: This feature is not yet implemented and will have no effect.
 */

export function withPrintDirection_(self, direction) {
  return addAction(self, new Actions.SetPrintDirection({
    direction
  }));
}
/**
 * Use the specified print direction to render the text.
 *
 * **NOTE**: This feature is not yet implemented and will have no effect.
 *
 * @ets_data_first withPrintDirection_
 */

export function withPrintDirection(direction) {
  return self => withPrintDirection_(self, direction);
}
/**
 * Use the default justification to render the text.
 *
 * **NOTE**: This feature is not yet implemented and will have no effect.
 */

export function withDefaultJustification(self) {
  return addAction(self, new Actions.DefaultJustification());
}
/**
 * Use the specified justification to render the text.
 *
 * **NOTE**: This feature is not yet implemented and will have no effect.
 */

export function withJustification_(self, justification) {
  return addAction(self, new Actions.SetJustification({
    justification
  }));
}
/**
 * Use the specified justification to render the text.
 *
 * **NOTE**: This feature is not yet implemented and will have no effect.
 *
 * @ets_data_first withJustification_
 */

export function withJustification(justification) {
  return self => withJustification_(self, justification);
} // -----------------------------------------------------------------------------
// Destructors
// -----------------------------------------------------------------------------

export function toBuildData(self) {
  return T.chain_(FigletClient.defaultFont, defaultFont => C.reduceEffect_(self.actions, buildData(), (data, action) => {
    return T.matchTag({
      // Fonts
      DefaultFont: () => T.map_(FigletClient.loadFontInternal(defaultFont), font => data.copy({
        font: O.some(font)
      })),
      SetFont: _ => T.succeed(data.copy({
        font: O.some(_.font)
      })),
      LoadFont: _ => T.map_(FigletClient.loadFont(_.fontPath), font => data.copy({
        font: O.some(font)
      })),
      LoadInternalFont: _ => T.map_(FigletClient.loadFontInternal(_.font), font => data.copy({
        font: O.some(font)
      })),
      // Horizontal Layout
      DefaultHorizontalLayout: () => T.succeed(data.copy({
        horizontalLayout: HL.FontDefault
      })),
      SetHorizontalLayout: _ => T.succeed(data.copy({
        horizontalLayout: _.layout
      })),
      // Justification
      DefaultJustification: () => T.succeed(data.copy({
        justification: J.FontDefault
      })),
      SetJustification: _ => T.succeed(data.copy({
        justification: _.justification
      })),
      // Max Width
      DefaultMaxWidth: () => T.succeed(data.copy({
        maxWidth: O.none
      })),
      SetMaxWidth: _ => T.succeed(data.copy({
        maxWidth: O.some(_.maxWidth)
      })),
      // Print Direction
      DefaultPrintDirection: () => T.succeed(data.copy({
        printDirection: PD.FontDefault
      })),
      SetPrintDirection: _ => T.succeed(data.copy({
        printDirection: _.direction
      })),
      // Text
      SetText: _ => T.succeed(data.copy({
        text: _.text
      }))
    })(action);
  }));
}
export function toRenderOptions(self) {
  return T.map_(T.bind_(T.bind_(T.bind_(T.do, "options", () => toBuildData(self)), "font", ({
    options
  }) => O.fold_(options.font, () => T.chain_(FigletClient.defaultFont, FigletClient.loadFontInternal), T.succeed)), "maxWidth", ({
    options
  }) => O.fold_(options.maxWidth, () => FigletClient.defaultMaxWidth, T.succeed)), ({
    font,
    maxWidth,
    options
  }) => new RenderOptions({
    font,
    maxWidth,
    horizontalLayout: options.horizontalLayout,
    justification: options.justification,
    printDirection: options.printDirection
  }));
}
export function renderToFigure(self) {
  return T.map_(T.bind_(T.bind_(T.do, "buildOptions", () => toBuildData(self)), "renderOptions", () => toRenderOptions(self)), ({
    buildOptions,
    renderOptions
  }) => FigletClient.renderToFigure(buildOptions.text, renderOptions));
}
export function renderToString(self) {
  return T.map_(renderToFigure(self), Fig.showFigure.show);
} // -----------------------------------------------------------------------------
// Utilities
// -----------------------------------------------------------------------------

function addAction(self, action) {
  return new OptionsBuilder(C.prepend_(C.filter_(self.actions, not(Actions.sameGroupAs(action))), action));
}
//# sourceMappingURL=index.mjs.map