"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.FigCharacter = void 0;
exports.columns = columns;
exports.equalFigCharacter = void 0;
exports.make = make;
exports.makeFromHeader = makeFromHeader;

var _Case = /*#__PURE__*/require("@effect-ts/core/Case");

var A = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect-ts/core/Collections/Immutable/Array"));

var C = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect-ts/core/Collections/Immutable/Chunk"));

var NA = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect-ts/core/Collections/Immutable/NonEmptyArray"));

var E = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect-ts/core/Either"));

var Eq = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect-ts/core/Equal"));

var _Function = /*#__PURE__*/require("@effect-ts/core/Function");

var O = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect-ts/core/Option"));

var String = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect-ts/core/String"));

var Structural = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect-ts/core/Structural"));

var _index = /*#__PURE__*/require("../FigletException/index.js");

var SL = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../SubLines/index.js"));

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

// ets_tracing: off
// -----------------------------------------------------------------------------
// Model
// -----------------------------------------------------------------------------

/**
 * The definition of a single Figlet character, part of a FigFont, which is
 * composed of `SubLines`.
 *
 * A `FigCharacter` cannot be instantiated directly. Instead, one must use one
 * of the provided constructors to perform validation of the defining lines
 * of the character.
 */
class FigCharacter extends _Case.Case {} // -----------------------------------------------------------------------------
// Constructors
// -----------------------------------------------------------------------------

/**
 * Creates a `FigCharacter` and validates the height and width of the specified
 * `lines`.
 *
 * @param fontId The identifier code of the `FigFont` where this `FigCharacter`
 * belongs.
 * @param maxWidth The maximum width that the `FigCharacter` can have.
 * @param height The height of the `FigCharacter` that must be respected.
 * @param name The name of the `FigCharacter`, which is the character that this
 * `FigCharacter` represents.
 * @param lines The strings composing the lines of the `FigCharacter`.
 * @param comment The comment of the `FigCharacter` present only if it is not
 * part of the required characters.
 * @param position
 * @returns A `FigletResult` containing the new `FigCharacter`, or a list of
 * `FigletException`s that occurred during parsing.
 */


exports.FigCharacter = FigCharacter;

function make(fontId, maxWidth, height, name, lines, comment, position) {
  const maxWidthV = validateMaxWidthArg(maxWidth);
  const nameV = validateName(name);
  const endmarkV = validateEndmark(name, position, lines);
  const cleanLinesV = E.chain_(endmarkV, endmark => cleanLines(endmark, lines));
  const argHeightV = validateHeightArg(height);
  const widthV = E.chain_(E.tuple(maxWidthV, cleanLinesV), ([maxWidth, lines]) => validateWidth(name, maxWidth, position, lines));
  const heightV = E.chain_(E.tuple(argHeightV, cleanLinesV), ([height, lines]) => validateHeight(name, position, height, lines));
  return E.chain_(heightV, () => E.map_(E.struct({
    fontId: E.right(fontId),
    name: nameV,
    lines: cleanLinesV,
    endmark: endmarkV,
    width: widthV,
    comment: E.right(comment),
    position: E.right(position)
  }), _ => new FigCharacter(_)));
}
/**
 * Creates a `FigCharacter` using a `FigHeader` to validate the specified
 * `lines`.
 *
 * @param fontId The identifier code of the `FigFont` where this `FigCharacter`
 * belongs.
 * @param header The `FigHeader` that will be used to validate the `lines`.
 * @param name The name of the `FigCharacter`, which is the character that this
 * `FigCharacter` represents.
 * @param lines The strings composing the lines of the `FigCharacter`.
 * @param comment The comment of the `FigCharacter` present only if it is not
 * part of the required characters.
 * @param position
 * @returns A `FigletResult` containing the new `FigCharacter`, or a list of
 * `FigletException`s that occurred during parsing.
 */


function makeFromHeader(fontId, header, name, lines, comment, position) {
  return make(fontId, header.maxLength, header.height, name, lines, comment, position);
} // -----------------------------------------------------------------------------
// Destructors
// -----------------------------------------------------------------------------

/**
 * Converts a `FigCharacter` into `SubColumns`.
 */


function columns(self) {
  return SL.toSubcolumns(self.lines);
} // -----------------------------------------------------------------------------
// Validation
// -----------------------------------------------------------------------------

/**
 * Removes the endmarks from the lines of the character.
 */


function cleanLines(endmark, lines) {
  const regex = endmark.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "{1,2}$";
  const find = new RegExp(regex, "g");
  return E.right(SL.map_(lines, String.replace(find, "")));
}
/**
 * Validates the name of a `FigCharacter`.
 */


function validateName(name) {
  return name !== "\uffff" ? E.right(name) : E.left([new _index.FigCharacterError({
    message: `Name "-1" is invalid`
  })]);
}
/**
 * Validates the maximum width argument provided when creating a `FigCharacter`.
 */


function validateMaxWidthArg(maxWidth) {
  return E.fromPredicate_(maxWidth, w => w > 0, w => [new _index.FigHeaderError({
    message: `Value of "maxLength" must be positive, received: ${w}`
  })]);
}
/**
 */


function validateHeightArg(height) {
  return E.fromPredicate_(height, h => h > 0, h => [new _index.FigHeaderError({
    message: `Value of "height" must be positive, received: ${h}`
  })]);
}
/**
 * Validates the endmark for all lines.
 */


function validateEndmark(name, position, lines) {
  const linesTerminations = A.map_(A.chain_(C.toArray(lines.value), line => O.fold_(A.head(O.getOrElse_(String.match_(line, /(.)\1?$/), () => A.empty())), () => A.empty(), A.single)), String.trim);
  const extractedEndmarksV = linesTerminations.every(l => l.length > 0 && l.length <= 2) ? E.right(A.uniq(Eq.string)(A.chain_(linesTerminations, String.split("")))) : E.left(NA.single(new _index.FigCharacterError({
    message: "Cannot determine endmark. There are lines with no termination or " + `more than 2-characters termination on character "${name}" defined ` + `at line ${position + 1}: (${linesTerminations.join(", ")})`
  })));
  return E.chain_(extractedEndmarksV, A.foldLeft(() => E.left(NA.single(new _index.FigCharacterError({
    message: `Can't determine endmark for character "${name}" defined at ` + `line ${position + 1}`
  }))), (head, tail) => A.isEmpty(tail) ? E.right(head) : E.left(NA.single(new _index.FigCharacterError({
    message: `Multiple endmarks found for character "${name}" defined at ` + `line ${position + 1}, only one endmark character is allowed: ` + `(${linesTerminations.join(", ")})`
  })))));
}

function validateWidth(name, maxLength, position, cleanLines) {
  const allLinesWidth = A.uniq(Eq.number)(A.map_(C.toArray(cleanLines.value), _ => _.length));

  if (maxLength <= 0) {
    return E.left(NA.single(new _index.FigCharacterError({
      message: `The argument "maxLength" must be greater than zero, received: ${maxLength}`
    })));
  }

  return O.fold_(O.filter_(A.head(allLinesWidth), () => allLinesWidth.length === 1), () => E.left(NA.single(new _index.FigCharacterError({
    message: `Lines for character "${name}" defined at line ${position + 1} ` + `are of different width: ${SL.showSubLines.show(cleanLines)}`
  }))), width => width <= maxLength ? E.right(width) : E.left(NA.single(new _index.FigCharacterError({
    message: `Maximum character width exceeded at line ${position + 1}`
  }))));
}

function validateHeight(name, position, height, cleanLines) {
  if (height <= 0) {
    return E.left(NA.single(new _index.FigCharacterError({
      message: `The argument "height" must be greater than zero, received: ${height}`
    })));
  }

  if (cleanLines.value.length === height) {
    return E.right(height);
  }

  return E.left(NA.single(new _index.FigCharacterError({
    message: `The character "${name}" defined at line ${position + 1} doesn't ` + `respect the specified height of ${height}`
  })));
} // -----------------------------------------------------------------------------
// Instances
// -----------------------------------------------------------------------------


const equalFigCharacter = /*#__PURE__*/Eq.makeEqual(Structural.equals);
exports.equalFigCharacter = equalFigCharacter;
//# sourceMappingURL=index.js.map