type Millenium = number;
type TerranDate = Date;

type Check = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
type YearFraction = number;
type Year = number;
interface ClassicDate {
    check: Check;
    fraction: YearFraction;
    year: Year;
    millenium: Millenium;
}
interface ClassicImperialDate extends ClassicDate {
    toString: (format?: string) => string;
    toDate: () => TerranDate;
}

type ImperialDate = ClassicDate | IndomitusEraDate;
interface DateSegment<T extends ImperialDate> {
    symbol: string;
    expression: string;
    format: (date: T) => string;
    parse: (date: T, value: string) => void;
}
declare enum Formats {
    CLASSIC_DEFAULT_FORMAT = "c fff yyy.m",
    CLASSIC_SHORT_FORMAT = "yyy.m",
    INDOMITUS_ERA_DEFAULT_FORMAT = "y.f gg d.m",
    INDOMITUS_ERA_SHORT_FORMAT = "y.fg d.m"
}

type Chronosegments = number;
type AnnualDesignator = number;
type Designator = string;
interface IndomitusEraDate {
    chronosegments: Chronosegments;
    annualDesignator: AnnualDesignator;
    millenium: Millenium;
    designator: Designator;
    isPostGreatRift: boolean;
}
interface IndomitusEraImperialDate extends IndomitusEraDate {
    toString: (format?: string) => string;
    toDate: () => TerranDate;
}

declare class ClassicImperialCalendar {
    static readonly GREAT_RIFT_OPENING: ClassicImperialDate;
    parse(date: TerranDate): ClassicImperialDate;
    parse(date: ClassicDate): ClassicImperialDate;
    parse(date: IndomitusEraDate): ClassicImperialDate;
    parse(date: string, format?: string): ClassicImperialDate;
    format(date: string, format?: string): string;
    format(date: TerranDate, format?: string): string;
    format(date: ClassicDate, format?: string): string;
    isValid(date: ClassicDate): boolean;
    getTerranDate(date: ClassicDate): TerranDate;
    getTerranDate(date: string, format?: string): TerranDate;
    private internalParse;
    private fromString;
    private fromTerranDate;
    private fromClassicImperialDate;
    private fromIndomitusEraDate;
}

declare class IndomitusEraImperialCalendar {
    parse(date: TerranDate): IndomitusEraImperialDate;
    parse(date: IndomitusEraDate): IndomitusEraImperialDate;
    parse(date: ClassicDate): IndomitusEraImperialDate;
    parse(date: string, format?: string): IndomitusEraImperialDate;
    format(date: string, format?: string): string;
    format(date: TerranDate, format?: string): string;
    format(date: IndomitusEraDate, format?: string): string;
    format(date: ClassicDate, format?: string): string;
    isValid(date: IndomitusEraDate): boolean;
    getTerranDate(date: IndomitusEraDate): TerranDate;
    getTerranDate(date: string, format?: string): TerranDate;
    private internalParse;
    private fromString;
    private fromTerranDate;
    private fromIndomitusEraImperialDate;
    private fromClassicImperialDate;
}

declare class Chrono {
    /**
     * Calendar for handling dates in the old style (pre-great rift) of the imperial dating system
     *
     * E. g.:
     * - "0 000 999.M41"
     * - "005.M30"
     */
    static classic: ClassicImperialCalendar;
    /**
     * Calendar for handling dates in the old style (post-great rift) of the imperial dating system
     *
     * E. g.:
     * - 0.1 previo VCM.M41
     * - 1.1+ TCM.M41
     */
    static indomitus: IndomitusEraImperialCalendar;
    static parse: {
        (date: TerranDate): ClassicImperialDate;
        (date: ClassicDate): ClassicImperialDate;
        (date: IndomitusEraDate): ClassicImperialDate;
        (date: string, format?: string): ClassicImperialDate;
    };
    static format: {
        (date: string, format?: string): string;
        (date: TerranDate, format?: string): string;
        (date: ClassicDate, format?: string): string;
    };
    static valid: (date: ClassicDate) => boolean;
    static getTerranDate: {
        (date: ClassicDate): TerranDate;
        (date: string, format?: string): TerranDate;
    };
}

export { Chrono, type DateSegment, Formats, type ImperialDate };
