import { FromCognitoIdentityPoolParameters } from '@aws-sdk/credential-provider-cognito-identity/dist-types/fromCognitoIdentityPool';
import { AwsCredentialIdentity } from '@aws-sdk/types/dist-types/identity/AwsCredentialIdentity';

type StateType = 'Task' | 'Parallel' | 'Map' | 'Pass' | 'Wait' | 'Choice' | 'Succeed' | 'Fail';

interface BaseState {
    Type: StateType;
    Comment?: string;
}

type JSONPrimitiveValue = null | boolean | number | string;
type JSONArray = (JSONPrimitiveValue | JSONArray | JSONObject)[];
type JSONObject = {
    [key: string]: JSONPrimitiveValue | JSONObject | JSONArray;
};
type JSONValue = JSONPrimitiveValue | JSONObject | JSONArray;

type PayloadTemplate = JSONObject | JSONArray;
interface CanHaveInputPath {
    InputPath?: string | null;
}
interface CanHaveParameters {
    Parameters?: JSONValue;
}
interface CanHaveResultSelector {
    ResultSelector?: JSONValue;
}
interface CanHaveResultPath {
    ResultPath?: string | null;
}
interface CanHaveOutputPath {
    OutputPath?: string | null;
}

type StringOperatorNames = 'StringEquals' | 'StringLessThan' | 'StringGreaterThan' | 'StringLessThanEquals' | 'StringGreaterThanEquals' | 'StringMatches';
type StringPathOperatorNames = 'StringEqualsPath' | 'StringLessThanPath' | 'StringGreaterThanPath' | 'StringLessThanEqualsPath' | 'StringGreaterThanEqualsPath';
type NumericOperatorNames = 'NumericEquals' | 'NumericLessThan' | 'NumericGreaterThan' | 'NumericLessThanEquals' | 'NumericGreaterThanEquals';
type NumericPathOperatorNames = 'NumericEqualsPath' | 'NumericLessThanPath' | 'NumericGreaterThanPath' | 'NumericLessThanEqualsPath' | 'NumericGreaterThanEqualsPath';
type BooleanOperatorNames = 'BooleanEquals';
type BooleanPathOperatorNames = 'BooleanEqualsPath';
type TimestampOperatorNames = 'TimestampEquals' | 'TimestampLessThan' | 'TimestampGreaterThan' | 'TimestampLessThanEquals' | 'TimestampGreaterThanEquals';
type TimestampPathOperatorNames = 'TimestampEqualsPath' | 'TimestampLessThanPath' | 'TimestampGreaterThanPath' | 'TimestampLessThanEqualsPath' | 'TimestampGreaterThanEqualsPath';
type TypeTestOperatorNames = 'IsNull' | 'IsPresent' | 'IsNumeric' | 'IsString' | 'IsBoolean' | 'IsTimestamp';
type StringComparisonOperator = {
    [P in StringOperatorNames]?: string;
};
type StringPathComparisonOperator = {
    [P in StringPathOperatorNames]?: string;
};
type NumericComparisonOperator = {
    [P in NumericOperatorNames]?: number;
};
type NumericPathComparisonOperator = {
    [P in NumericPathOperatorNames]?: string;
};
type BooleanComparisonOperator = {
    [P in BooleanOperatorNames]?: boolean;
};
type BooleanPathComparisonOperator = {
    [P in BooleanPathOperatorNames]?: string;
};
type TimestampComparisonOperator = {
    [P in TimestampOperatorNames]?: string;
};
type TimestampPathComparisonOperator = {
    [P in TimestampPathOperatorNames]?: string;
};
type TypeTestComparisonOperator = {
    [P in TypeTestOperatorNames]?: true;
};
type ComparisonOperator = StringComparisonOperator | StringPathComparisonOperator | NumericComparisonOperator | NumericPathComparisonOperator | BooleanComparisonOperator | BooleanPathComparisonOperator | TimestampComparisonOperator | TimestampPathComparisonOperator | TypeTestComparisonOperator;
type BaseDataTestExpression = {
    Variable: string;
};
type DataTestExpression = BaseDataTestExpression & ComparisonOperator;
type BooleanExpression = {
    And?: ChoiceRuleWithoutNext[];
    Or?: ChoiceRuleWithoutNext[];
    Not?: ChoiceRuleWithoutNext;
};
type ChoiceRuleWithoutNext = DataTestExpression | BooleanExpression;
type ChoiceRule = (DataTestExpression | BooleanExpression) & {
    Next: string;
};
interface BaseChoiceState extends BaseState, CanHaveInputPath, CanHaveOutputPath {
    Type: 'Choice';
    Choices: ChoiceRule[];
    Default?: string;
}
type ChoiceState = BaseChoiceState;

interface EndableState extends BaseState {
    Type: Exclude<StateType, 'Choice' | 'Succeed' | 'Fail'>;
    End: true;
}
interface SucceedOrFailState extends BaseState {
    Type: Extract<StateType, 'Succeed' | 'Fail'>;
}
type TerminalState = EndableState | SucceedOrFailState;

interface BaseFailState extends BaseState {
    Type: 'Fail';
    Cause?: string;
    CausePath?: string;
    Error?: string;
    ErrorPath?: string;
}
type FailState = TerminalState & BaseFailState;

type Retrier = {
    ErrorEquals: string[];
    IntervalSeconds?: number;
    MaxAttempts?: number;
    BackoffRate?: number;
    MaxDelaySeconds?: number;
    JitterStrategy?: 'NONE' | 'FULL';
};
interface RetryableState {
    Retry?: Retrier[];
}
type Catcher = {
    ErrorEquals: string[];
    Next: string;
    ResultPath?: string;
};
interface CatchableState {
    Catch?: Catcher[];
}

interface NextableState extends BaseState {
    Type: Exclude<StateType, 'Choice' | 'Succeed' | 'Fail'>;
    Next: string;
}
type IntermediateState = NextableState;

interface BaseMapState extends BaseState, CanHaveInputPath, CanHaveResultSelector, CanHaveResultPath, CanHaveOutputPath, RetryableState, CatchableState {
    Type: 'Map';
    Iterator?: Omit<StateMachineDefinition, 'Version' | 'TimeoutSeconds'>;
    ItemProcessor?: Omit<StateMachineDefinition, 'Version' | 'TimeoutSeconds'>;
    Parameters?: PayloadTemplate;
    ItemSelector?: PayloadTemplate;
    ItemsPath?: string;
    MaxConcurrency?: number;
    MaxConcurrencyPath?: string;
}
type MapState = (IntermediateState | TerminalState) & BaseMapState;

interface BaseParallelState extends BaseState, CanHaveInputPath, CanHaveParameters, CanHaveResultSelector, CanHaveResultPath, CanHaveOutputPath, RetryableState, CatchableState {
    Type: 'Parallel';
    Branches: Omit<StateMachineDefinition, 'Version' | 'TimeoutSeconds'>[];
}
type ParallelState = (IntermediateState | TerminalState) & BaseParallelState;

interface BasePassState extends BaseState, CanHaveInputPath, CanHaveParameters, CanHaveResultPath, CanHaveOutputPath {
    Type: 'Pass';
    Result?: JSONValue;
}
type PassState = (IntermediateState | TerminalState) & BasePassState;

interface BaseSucceedState extends BaseState, CanHaveInputPath, CanHaveOutputPath {
    Type: 'Succeed';
}
type SucceedState = TerminalState & BaseSucceedState;

interface BaseTaskState extends BaseState, CanHaveInputPath, CanHaveParameters, CanHaveResultSelector, CanHaveResultPath, CanHaveOutputPath, RetryableState, CatchableState {
    Type: 'Task';
    Resource: string;
    TimeoutSeconds?: number;
    TimeoutSecondsPath?: string;
}
type TaskState = (IntermediateState | TerminalState) & BaseTaskState;

interface BaseWaitState extends BaseState, CanHaveInputPath, CanHaveOutputPath {
    Type: 'Wait';
    Seconds?: number;
    Timestamp?: string;
    SecondsPath?: string;
    TimestampPath?: string;
}
type WaitState = (IntermediateState | TerminalState) & BaseWaitState;

type AllStates = TaskState | ParallelState | MapState | PassState | WaitState | ChoiceState | SucceedState | FailState;

interface StateMachineDefinition {
    States: Record<string, AllStates>;
    StartAt: string;
    Comment?: string;
    Version?: string;
    TimeoutSeconds?: number;
}

type ContextExecution = {
    Input?: JSONValue;
    StartTime?: string;
    [other: string]: unknown;
};
type Context = {
    Execution?: ContextExecution;
    [other: string]: unknown;
};

/**
 * Base class for all internal errors that can be thrown during the state machine execution.
 */
declare abstract class RuntimeError extends Error {
    /**
     * Whether this runtime error can be matched in a `Retry` field
     */
    protected retryable: boolean;
    /**
     * Whether this runtime error can be caught in a `Catch` field
     */
    protected catchable: boolean;
    constructor(message: string, cause?: unknown);
    get isRetryable(): boolean;
    get isCatchable(): boolean;
}

type ExecutionStartedEventType = 'ExecutionStarted';
type ExecutionSucceededEventType = 'ExecutionSucceeded';
type ExecutionFailedEventType = 'ExecutionFailed';
type ExecutionTerminatedEventType = 'ExecutionAborted' | 'ExecutionTimeout';
type ExecutionEventType = ExecutionStartedEventType | ExecutionSucceededEventType | ExecutionFailedEventType | ExecutionTerminatedEventType;
type MapIterationStartedEventType = 'MapIterationStarted';
type MapIterationSucceededEventType = 'MapIterationSucceeded';
type MapIterationFailedEventType = 'MapIterationFailed';
type MapIterationEventType = MapIterationStartedEventType | MapIterationSucceededEventType | MapIterationFailedEventType;
type ParallelBranchStartedEventType = 'ParallelBranchStarted';
type ParallelBranchSucceededEventType = 'ParallelBranchSucceeded';
type ParallelBranchFailedEventType = 'ParallelBranchFailed';
type ParallelBranchEventType = ParallelBranchStartedEventType | ParallelBranchSucceededEventType | ParallelBranchFailedEventType;
type StateEnteredEventType = 'StateEntered';
type StateExitedEventType = 'StateExited';
type StateFailedEventType = 'StateFailed';
type StateRetriedEventType = 'StateRetried';
type StateCaughtEventType = 'StateCaught';
type StateEventType = StateEnteredEventType | StateExitedEventType | StateFailedEventType | StateRetriedEventType | StateCaughtEventType;
type AllEventTypes = ExecutionEventType | MapIterationEventType | ParallelBranchEventType | StateEventType;
interface StateData {
    name: string;
    type: StateType;
    input: JSONValue;
    output?: JSONValue;
}
interface RetryData {
    retrier: Retrier;
    attempt: number;
}
interface CatchData {
    catcher: Catcher;
}
interface ErrorInfo {
    Error: string;
    Cause: unknown;
}
interface BaseEvent {
    type: AllEventTypes;
    timestamp: number;
}
interface ExecutionStartedEvent extends BaseEvent {
    type: ExecutionStartedEventType;
    input: JSONValue;
}
interface ExecutionSucceededEvent extends BaseEvent {
    type: ExecutionSucceededEventType;
    output: JSONValue;
}
interface ExecutionFailedEvent extends BaseEvent, ErrorInfo {
    type: ExecutionFailedEventType;
}
interface ExecutionTerminatedEvent extends BaseEvent {
    type: ExecutionTerminatedEventType;
}
interface BaseMapIterationEvent extends BaseEvent {
    type: MapIterationEventType;
    parentState: StateData;
    index: number;
}
interface MapIterationStartedEvent extends BaseMapIterationEvent {
    type: MapIterationStartedEventType;
}
interface MapIterationSucceededEvent extends BaseMapIterationEvent {
    type: MapIterationSucceededEventType;
}
interface MapIterationFailedEvent extends BaseMapIterationEvent, ErrorInfo {
    type: MapIterationFailedEventType;
}
interface BaseParallelBranchEvent extends BaseEvent {
    type: ParallelBranchEventType;
    parentState: StateData;
}
interface ParallelBranchStartedEvent extends BaseParallelBranchEvent {
    type: ParallelBranchStartedEventType;
}
interface ParallelBranchSucceededEvent extends BaseParallelBranchEvent {
    type: ParallelBranchSucceededEventType;
}
interface ParallelBranchFailedEvent extends BaseParallelBranchEvent, ErrorInfo {
    type: ParallelBranchFailedEventType;
}
interface BaseStateEvent extends BaseEvent {
    type: StateEventType;
    state: StateData;
    index?: number;
}
interface StateEnteredEvent extends BaseStateEvent {
    type: StateEnteredEventType;
}
interface StateExitedEvent extends BaseStateEvent {
    type: StateExitedEventType;
}
interface StateFailedEvent extends BaseStateEvent, ErrorInfo {
    type: StateFailedEventType;
}
interface StateRetriedEvent extends BaseStateEvent {
    type: StateRetriedEventType;
    retry: RetryData;
}
interface StateRetriedEvent extends BaseStateEvent {
    type: StateRetriedEventType;
    retry: RetryData;
}
interface StateCaughtEvent extends BaseStateEvent {
    type: StateCaughtEventType;
    catch: CatchData;
}
type EventLog = ExecutionStartedEvent | ExecutionSucceededEvent | ExecutionFailedEvent | ExecutionTerminatedEvent | MapIterationStartedEvent | MapIterationSucceededEvent | MapIterationFailedEvent | ParallelBranchStartedEvent | ParallelBranchSucceededEvent | ParallelBranchFailedEvent | StateEnteredEvent | StateExitedEvent | StateFailedEvent | StateRetriedEvent | StateCaughtEvent;

type TaskStateResourceLocalHandler = {
    [taskStateName: string]: (input: JSONValue) => Promise<JSONValue> | JSONValue;
};
type WaitStateTimeOverride = {
    [waitStateName: string]: number;
};
type RetryIntervalOverrides = {
    [retryableStateName: string]: number | number[];
};
interface Overrides {
    /**
     * Pass an object to this option to override a `Task` state to run a local function,
     * instead of calling the service specified in the `Resource` field.
     */
    taskResourceLocalHandlers?: TaskStateResourceLocalHandler;
    /**
     * Pass an object to this option to override a `Wait` state to pause for the specified number of milliseconds,
     * instead of pausing for the duration specified by the `Seconds`, `Timestamp`, `SecondsPath`, or `TimestampPath` fields.
     */
    waitTimeOverrides?: WaitStateTimeOverride;
    /**
     * Pass an object to this option to override the duration in milliseconds a retrier in a `Retry` field waits before retrying the state,
     * instead of pausing for the duration calculated by the `IntervalSeconds`, `BackoffRate`, `MaxDelaySeconds`, and `JitterStrategy` fields.
     */
    retryIntervalOverrides?: RetryIntervalOverrides;
}
interface ValidationOptions {
    /**
     * Disables validation of the state machine definition entirely.
     *
     * Use this option at your own risk, there are no guarantees when passing an invalid or non-standard definition to the state machine.
     * Running it might result in undefined/unsupported behavior.
     */
    readonly noValidate?: boolean;
    /**
     * Disables validation of JSONPath expressions in the state machine definition.
     */
    readonly checkPaths?: boolean;
    /**
     * Disables validation of ARNs in the state machine definition.
     */
    readonly checkArn?: boolean;
}
interface AWSConfig {
    /**
     * AWS Region where your Task resources are located.
     */
    region: string;
    /**
     * AWS credentials needed to be able to call Task resources.
     */
    credentials?: {
        cognitoIdentityPool?: FromCognitoIdentityPoolParameters;
        accessKeys?: AwsCredentialIdentity;
    };
}
interface StateMachineOptions {
    /**
     * Options that allow changing certain rules when validating the state machine definition.
     */
    validationOptions?: ValidationOptions;
    /**
     * Config options related to AWS resources.
     */
    awsConfig?: AWSConfig;
}
interface RunOptions {
    /**
     * This option allows overriding the behavior of certain states.
     */
    overrides?: Overrides;
    /**
     * If set to `true`, aborting the execution will simply return `null` as result instead of throwing
     */
    noThrowOnAbort?: boolean;
    /**
     * Pass an object to this option to mock the [Context Object](https://states-language.net/#context-object) that will be used in the execution.
     * @see https://docs.aws.amazon.com/step-functions/latest/dg/input-output-contextobject.html
     */
    context?: Context;
}

declare class StateMachine {
    /**
     * The structure of the State Machine as represented by the Amazon States Language.
     */
    private readonly definition;
    /**
     * Options to control certain settings of the state machine.
     */
    private readonly stateMachineOptions;
    /**
     * Constructs a new state machine.
     * @param definition The state machine definition defined using the Amazon States Language (https://states-language.net/spec.html).
     * @param stateMachineOptions Options to control certain settings of the state machine.
     * These options also apply to state machines defined in the `Iterator` field of `Map` states and in the `Branches` field of `Parallel` states.
     */
    constructor(definition: StateMachineDefinition, stateMachineOptions?: StateMachineOptions);
    /**
     * Executes the state machine, running through the states specified in the definition.
     * If the execution fails, the result will throw an `ExecutionError` explaining why the
     * execution failed.
     *
     * If the execution times out because the number of seconds specified in
     * the `TimeoutSeconds` top-level field has elapsed, the result will throw an `ExecutionTimeoutError`.
     *
     * By default, if the execution is aborted, the result will throw an `ExecutionAbortedError`. This behavior can be changed by setting
     * the `noThrowOnAbort` option to `true`, in which case the result will be `null`.
     *
     * @param input The input to pass to this state machine execution.
     * @param options Miscellaneous options to control certain behaviors of the execution.
     */
    run(input: JSONValue, options?: RunOptions): {
        abort: () => void;
        result: Promise<JSONValue>;
        eventLogs: AsyncGenerator<EventLog>;
    };
    /**
     * Helper method that handles the execution of the machine states and the transitions between them.
     */
    private execute;
}

/**
 * Represents the failure of a state machine execution.
 */
declare class ExecutionError extends Error {
    constructor(caughtError: RuntimeError);
}

/**
 * Represents the abort of a state machine execution.
 */
declare class ExecutionAbortedError extends Error {
    constructor();
}

/**
 * Represents the timeout of a state machine execution.
 */
declare class ExecutionTimeoutError extends Error {
    constructor();
}

export { ExecutionAbortedError, ExecutionError, ExecutionTimeoutError, type RunOptions, StateMachine, type StateMachineDefinition, type StateMachineOptions };
