import { Fixed } from "../Fixed" import type { Currency } from "./" import { decimals } from "./decimals" export class Amount { get value(): number { return this.backend.value } get major(): number { return Math.floor(this.backend.value) } get minor(): number { return this.decimals ? this.backend.value * 10 ** this.decimals : this.backend.value } private constructor( private readonly backend: Fixed, readonly currency: C, readonly decimals: undefined | 0 | 2 | 3 | 4 ) {} create(value: number): Amount { return Amount.create(this.currency, value) } add(term: number | Amount): Amount { return this.create(this.backend.add(typeof term == "number" ? term : term.backend).value) } subtract(minuend: number | Amount): Amount { return this.create(this.backend.subtract(typeof minuend == "number" ? minuend : minuend.backend).value) } multiply(multiplicand: number | Amount): Amount { return this.create( this.backend.multiply(typeof multiplicand == "number" ? multiplicand : multiplicand.backend).value ) } convert(factor: number, to: D): Amount { return Amount.create(to, this.value * factor) } divide(denominator: number | Amount): Amount { return this.create(this.backend.divide(typeof denominator == "number" ? denominator : denominator.backend).value) } toJSON(): [number, C] { return [this.backend.value, this.currency] } toString(): string { return `${this.backend.toString()} ${this.currency}` } static create(currency: C, value: number): Amount { const d = decimals(currency) return new Amount(Fixed.create(value, d ?? 2), currency, d) } static fromMinor(currency: C, value: number): Amount { return this.create(currency, value / 10 ** (decimals(currency) ?? 2)) } static add(currency: C, value: number, term: number | Amount): Amount { return this.create(currency, value).add(term) } static subtract(currency: C, value: number, minuend: number | Amount): Amount { return this.create(currency, value).subtract(minuend) } static multiply(currency: C, value: number, multiplicand: number | Amount): Amount { return this.create(currency, value).multiply(multiplicand) } static convert(currency: Currency, value: number, factor: number, to: C): Amount { return this.create(currency, value).convert(factor, to) } static divide(currency: C, value: number, denominator: number | Amount): Amount { return this.create(currency, value).divide(denominator) } } export namespace Amount {}