import { RetryOptions } from "@atomist/automation-client/lib/util/retry";
import { InterpretLog } from "../../spi/log/InterpretedLog";
import { DefaultFacts, StatefulPushListenerInvocation } from "../dsl/goalContribution";
import { GoalExecutionListener } from "../listener/GoalStatusListener";
import { Registerable } from "../machine/Registerable";
import { SoftwareDeliveryMachine } from "../machine/SoftwareDeliveryMachine";
import { PushTest } from "../mapping/PushTest";
import { ServiceRegistration } from "../registration/ServiceRegistration";
import { WaitRules } from "./common/createGoal";
import { Goal, GoalDefinition, GoalWithPrecondition } from "./Goal";
import { ExecuteGoal, GoalProjectListenerRegistration } from "./GoalInvocation";
import { Goals } from "./Goals";
import { ReportProgress } from "./progress/ReportProgress";
import { GoalEnvironment } from "./support/environment";
import { GoalFulfillmentCallback } from "./support/GoalImplementationMapper";
export declare type Fulfillment = Implementation | SideEffect;
/**
 * Register a fulfillment with basic details
 */
export interface FulfillmentRegistration {
    /**
     * Name of goal implementation
     */
    name: string;
    /**
     * Optional push test to identify the types of projects and pushes this implementation
     * should get invoked on when the goal gets scheduled
     */
    pushTest?: PushTest;
}
/**
 * Register a goal implementation with required details
 */
export interface ImplementationRegistration extends FulfillmentRegistration {
    /**
     * Optional log interpreter for this goal implementations log output
     */
    logInterpreter?: InterpretLog;
    /**
     * Optional progress reporter for this goal implementation
     */
    progressReporter?: ReportProgress;
}
export interface Implementation extends ImplementationRegistration {
    goalExecutor: ExecuteGoal;
}
export declare function isImplementation(f: Fulfillment): f is Implementation;
export interface SideEffect {
    name: string;
    registration: string;
    pushTest?: PushTest;
}
export declare function isSideEffect(f: Fulfillment): f is SideEffect;
/**
 * Subset of the GoalDefinition interface to use by typed Goals to allow
 * specifying some aspect of the Goal that are specific to the current use case.
 */
export interface FulfillableGoalDetails {
    displayName?: string;
    uniqueName?: string;
    environment?: string | GoalEnvironment;
    approval?: boolean;
    preApproval?: boolean;
    retry?: boolean;
    isolate?: boolean;
    descriptions?: {
        planned?: string;
        requested?: string;
        completed?: string;
        inProcess?: string;
        failed?: string;
        waitingForApproval?: string;
        waitingForPreApproval?: string;
        canceled?: string;
        stopped?: string;
    };
    preCondition?: WaitRules;
    retryCondition?: RetryOptions;
}
/**
 * Extension to GoalDefinition that allows to specify additional WaitRules.
 */
export interface PredicatedGoalDefinition extends GoalDefinition {
    preCondition?: WaitRules;
    retryCondition?: RetryOptions;
}
export interface Parameterized {
    parameters?: DefaultFacts;
}
export interface PlannedGoal extends Parameterized {
    details?: Omit<FulfillableGoalDetails, "uniqueName" | "environment">;
    fulfillment?: {
        registration: string;
        name: string;
    };
}
export declare type PlannedGoals = Record<string, {
    goals: PlannedGoal | Array<PlannedGoal | PlannedGoal[]>;
    dependsOn?: string | string[];
}>;
export interface PlannableGoal {
    plan?(pli: StatefulPushListenerInvocation, goals: Goals): Promise<PlannedGoals | PlannedGoal>;
}
/**
 * Goal that registers goal implementations, side effects and callbacks on the
 * current SDM. No additional registration with the SDM is needed.
 */
export declare abstract class FulfillableGoal extends GoalWithPrecondition implements Registerable, PlannableGoal {
    definitionOrGoal: PredicatedGoalDefinition | Goal;
    readonly fulfillments: Fulfillment[];
    readonly callbacks: GoalFulfillmentCallback[];
    readonly projectListeners: GoalProjectListenerRegistration[];
    readonly goalListeners: GoalExecutionListener[];
    sdm: SoftwareDeliveryMachine;
    constructor(definitionOrGoal: PredicatedGoalDefinition | Goal, ...dependsOn: Goal[]);
    register(sdm: SoftwareDeliveryMachine): void;
    withProjectListener(listener: GoalProjectListenerRegistration): this;
    withExecutionListener(listener: GoalExecutionListener): this;
    withService(registration: ServiceRegistration<any>): this;
    protected addFulfillmentCallback(cb: GoalFulfillmentCallback): this;
    protected addFulfillment(fulfillment: Fulfillment): this;
    private registerFulfillment;
    plan(pli: StatefulPushListenerInvocation, goals: Goals): Promise<PlannedGoals | PlannedGoal>;
    private registerCallback;
}
/**
 * Goal that accepts registrations of R.
 */
export declare abstract class FulfillableGoalWithRegistrations<R> extends FulfillableGoal {
    definitionOrGoal: PredicatedGoalDefinition | Goal;
    readonly registrations: R[];
    constructor(definitionOrGoal: PredicatedGoalDefinition | Goal, ...dependsOn: Goal[]);
    with(registration: R): this;
}
/**
 * Goal that accepts registrations of R and listeners of L.
 */
export declare abstract class FulfillableGoalWithRegistrationsAndListeners<R, L> extends FulfillableGoalWithRegistrations<R> {
    definitionOrGoal: PredicatedGoalDefinition | Goal;
    readonly listeners: L[];
    constructor(definitionOrGoal: PredicatedGoalDefinition | Goal, ...dependsOn: Goal[]);
    withListener(listener: L): this;
}
/**
 * Generic goal that can be used with a GoalDefinition.
 * Register goal implementations or side effects to this goal instance.
 */
export declare class GoalWithFulfillment extends FulfillableGoal {
    withCallback(cb: GoalFulfillmentCallback): this;
    with(fulfillment: Fulfillment): this;
}
/**
 * Creates a new GoalWithFulfillment instance using conventions if overwrites aren't provided
 *
 * Call this from your machine.ts where you configure your sdm to create a custom goal.
 *
 * Caution: if you wrap this in another function, then you MUST provide details.uniqueName,
 *          because the default is based on where in the code this `goal` function is called.
 *
 * @param details It is highly recommended that you supply at least uniqueName.
 * @param goalExecutor
 * @param options
 */
export declare function goal(details?: FulfillableGoalDetails, goalExecutor?: ExecuteGoal, options?: {
    pushTest?: PushTest;
    logInterpreter?: InterpretLog;
    progressReporter?: ReportProgress;
    plan?: (pli: StatefulPushListenerInvocation, goals: Goals) => Promise<PlannedGoals | PlannedGoal>;
}): GoalWithFulfillment;
/**
 * Construct a PredicatedGoalDefinition from the provided goalDetails
 * @param goalDetails
 * @param uniqueName
 * @param definition
 */
export declare function getGoalDefinitionFrom(goalDetails: FulfillableGoalDetails | string, uniqueName: string, definition?: GoalDefinition): {
    uniqueName: string;
} | PredicatedGoalDefinition;
/**
 * Merge Goal configuration options into a final options object.
 * Starts off by merging the explicitly provided options over the provided defaults; finally merges the configuration
 * values at the given configuration path (prefixed with sdm.) over the previous merge.
 * @param defaults
 * @param explicit
 * @param configurationPath
 */
export declare function mergeOptions<OPTIONS>(defaults: OPTIONS, explicit: OPTIONS, configurationPath?: string): OPTIONS;
//# sourceMappingURL=GoalWithFulfillment.d.ts.map