import Crowdin, { SourceFilesModel, TranslationStatusModel } from '@crowdin/crowdin-api-client';
import { Request } from 'express';
import { CrowdinClientRequest, ModuleKey } from '../../types';
import { JobClient, JobStoreType } from './util/types';
export interface IntegrationLogic extends ModuleKey {
    /**
     * Customize your app login form
     */
    loginForm?: LoginForm;
    /**
     * Define login process via OAuth2 protocol
     */
    oauthLogin?: OAuthLogin;
    /**
     * name of the root folder in Crowdin where files from integration will be stored, default your app name, will be ignored in case if {@link withRootFolder} is false
     */
    appFolderName?: string;
    /**
     * flag that defines if the app should have a dedicated root folder in Crowdin files, default 'false'
     */
    withRootFolder?: boolean;
    /**
     * function which will be used to check connection with integration service
     */
    checkConnection?: (apiCredentials: any) => Promise<void>;
    /**
     * function to get crowdin files that are related with this integration
     */
    getCrowdinFiles?: (projectId: number, client: Crowdin, appRootFolder?: SourceFilesModel.Directory, config?: any) => Promise<TreeItem[]>;
    /**
     * function to get data from integration
     */
    getIntegrationFiles: (apiCredentials: any, config?: any, parentId?: any, search?: any, page?: any) => Promise<TreeItem[] | ExtendedResult<TreeItem[]>>;
    /**
     * function to update crowdin files (e.g. pull integration data to crowdin source files)
     */
    updateCrowdin: ({ projectId, client, credentials, request, rootFolder, appSettings, uploadTranslations, job, excludedTargetLanguages, }: {
        projectId: number;
        client: Crowdin;
        credentials: any;
        request: IntegrationFile[];
        rootFolder?: SourceFilesModel.Directory;
        appSettings?: any;
        uploadTranslations?: boolean;
        job: JobClient;
        excludedTargetLanguages?: string[];
    }) => Promise<void | ExtendedResult<void>>;
    /**
     * function to update integration content (e.g. load crowdin translations and push them to integration service)
     */
    updateIntegration: ({ projectId, client, credentials, request, rootFolder, appSettings, job, }: {
        projectId: number;
        client: Crowdin;
        credentials: any;
        request: UpdateIntegrationRequest;
        rootFolder?: SourceFilesModel.Directory;
        appSettings?: any;
        job: JobClient;
    }) => Promise<void | ExtendedResult<void>>;
    /**
     * Store to use for memorizing job data
     */
    jobStoreType?: JobStoreType;
    /**
     * function to define configuration(settings) modal for you app (by default app will not have any custom settings)
     */
    getConfiguration?: (projectId: number, client: Crowdin, apiCredentials: any) => Promise<FormEntity[]>;
    /**
     * function to normalize saved settings
     */
    normalizeSettings?: ({ appSettings, apiCredentials, client, }: {
        appSettings: FormEntity[];
        apiCredentials: any;
        client?: Crowdin;
    }) => Promise<FormEntity[]>;
    /**
     * Logout hook for cleanup logic
     */
    onLogout?: (projectId: number, client: Crowdin, apiCredentials: any, config?: any) => Promise<void>;
    /**
     * flag to turn on auto reload of the tree whenever user updates the configuration
     */
    reloadOnConfigSave?: boolean;
    /**
     * define info modal (help section) for you app (by default app will not have own info section)
     */
    infoModal?: {
        title: string;
        content: string;
    };
    /**
     * background jobs that will be executed for each crowdin project and user
     */
    cronJobs?: CronJob[];
    /**
     * Enable new file sync when syncing via cron or webhook
     */
    syncNewElements?: {
        crowdin: boolean;
        integration: boolean;
    };
    withCronSync?: {
        crowdin: boolean;
        integration: boolean;
    };
    withWebhookSync?: {
        crowdin: boolean;
        integration: boolean;
    };
    filtering?: {
        crowdinLanguages: boolean;
    };
    /**
     * Enable integration folder open event
     */
    integrationOneLevelFetching?: boolean;
    /**
     * Enable integration search event
     */
    integrationSearchListener?: boolean;
    /**
     * Enable integration next page event
     */
    integrationPagination?: boolean;
    /**
     * Enable the option to upload translations to crowdin that are already present in the integration.
     */
    uploadTranslations?: boolean;
    /**
     * Enable the option to upload file for translation into selected languages.
     */
    excludedTargetLanguages?: boolean;
    /**
     * function to get crowdin file translation progress
     */
    getFileProgress?: (projectId: number, client: Crowdin, fileId: number) => Promise<{
        [key: number]: TranslationStatusModel.LanguageProgress[];
    }>;
    /**
     * Register Crowdin webhook to get notified when translations are ready
     */
    webhooks?: Webhooks;
    /**
     * define a notification for your application at the top of the screen
     */
    notice?: {
        title: string;
        content: string;
        type: NoticeType;
        icon: boolean;
        close: boolean;
    };
    skipIntegrationNodes?: SkipIntegrationNodes;
    /**
     * Async progress checking time interval to update job progress, im ms.
     *
     * Default 1000
     */
    asyncProgress?: {
        checkInterval?: number;
    };
    /**
     * The duration for storing user errors, default is 30 days.
     */
    userErrorLifetimeDays?: number;
    /**
     * When true, folder filtering during automatic translation sync is bypassed, and the file tree is returned unchanged.
     */
    skipAutoSyncFoldersFilter?: boolean;
}
export interface LoginForm {
    fields: FormEntity[];
    /**
     * Override to implement request for retrieving access token (and refresh token if 'refresh' is enabled)
     */
    performGetTokenRequest?: (fieldsCredentials: any) => Promise<LoginFormTokenResponse>;
    /**
     * Override to implement request for refreshing token (only if 'refresh' is enabled)
     */
    performRefreshTokenRequest?: (currentCredentials: any) => Promise<LoginFormTokenResponse>;
    /**
     * default 'false' which means that the access token has no expiration date
     */
    refresh?: boolean;
}
export interface OAuthLogin {
    /**
     * Extra field for login form
     */
    loginFields?: FormField[];
    /**
     * Authorization url (e.g. https://github.com/login/oauth/authorize or https://accounts.google.com/o/oauth2/v2/auth)
     */
    authorizationUrl?: string;
    /**
     * Authorization url getter
     */
    getAuthorizationUrl?: (redirectUrl: string, loginForm: any) => string;
    /**
     * Access token url (e.g. https://github.com/login/oauth/access_token)
     */
    accessTokenUrl: string;
    /**
     * Url to refresh token, default will use {@link accessTokenUrl}. Needed when {@link refresh} is enabled
     */
    refreshTokenUrl?: string;
    mode?: 'standard' | 'polling';
    /**
     * The scopes of access, usually expressed as a list of space-delimited, case-sensitive strings
     */
    scope?: string;
    /**
     * Client id
     */
    clientId: string;
    /**
     * Client secret
     */
    clientSecret: string;
    /**
     * default '/oauth/code'
     */
    redirectUriRoute?: string;
    /**
     * request/response fields mapping
     */
    fieldsMapping?: {
        /**
         * default 'client_id'
         */
        clientId?: string;
        /**
         * default 'client_secret'
         */
        clientSecret?: string;
        /**
         * default 'scope'
         */
        scope?: string;
        /**
         * default 'redirect_uri'
         */
        redirectUri?: string;
        /**
         * default 'code'
         */
        code: string;
        /**
         * default 'access_token'
         */
        accessToken?: string;
        /**
         * default 'refresh_token'
         */
        refreshToken?: string;
        /**
         * default 'expires_in'
         */
        expiresIn?: string;
        /**
         * default 'state'
         */
        state?: string;
    };
    /**
     * default 'false' which means that the access token has no expiration date
     */
    refresh?: boolean;
    /**
     * Additional URL parameters for authorizarion url
     */
    extraAutorizationUrlParameters?: {
        [key: string]: string;
    };
    /**
     * Additional parameters for access token request
     */
    extraAccessTokenParameters?: {
        [key: string]: any;
    };
    /**
     * Additional parameters for refresh token request
     */
    extraRefreshTokenParameters?: {
        [key: string]: any;
    };
    /**
     * Override to implement request for retrieving access token (and refresh token if 'refresh' is enabled)
     */
    performGetTokenRequest?: (code: string, query: {
        [key: string]: any;
    }, url: string, redirectUri: string, loginForm?: any) => Promise<any>;
    /**
     * Override to implement request for refreshing token (only if 'refresh' is enabled)
     */
    performRefreshTokenRequest?: (currentCredentials: any, loginForm?: any) => Promise<any>;
}
export interface File {
    id: string;
    name: string;
    type: SourceFilesModel.FileType;
    parentId?: string;
    nodeType?: IntegrationTreeElementType;
    customContent?: string;
    labels?: LabelTreeElement[];
    failed?: boolean;
    excludedTargetLanguages?: string[];
}
export interface Folder {
    id: string;
    name: string;
    parentId?: string;
    nodeType?: IntegrationTreeElementType;
    customContent?: string;
    labels?: LabelTreeElement[];
}
export type TreeItem = File | Folder;
/**
 * 0 - folder
 * 1 - file
 * 2 - branch
 */
type IntegrationTreeElementType = '0' | '1' | '2';
export type FormEntity = FormField | FormDelimiter;
export interface FormDelimiter {
    label?: string;
    labelHtml?: string;
}
export interface FormField {
    key: string;
    helpText?: string;
    helpTextHtml?: string;
    label: string;
    type?: 'text' | 'password' | 'checkbox' | 'select' | 'textarea' | 'file' | 'notice';
    defaultValue?: any;
    /**
     * only for select
     */
    isMulti?: boolean;
    /**
     * only for select
     */
    isSearchable?: boolean;
    /**
     * only for select
     */
    options?: {
        label: string;
        value: string;
    }[];
    /**
     * only for type file
     */
    accept?: string;
    /**
     * field dependency settings
     */
    dependencySettings?: string;
    /**
     * only for notice type
     */
    noticeType?: string;
    /**
     * only for notice type
     */
    noIcon?: boolean;
}
type NoticeType = 'info' | 'warning' | 'danger' | 'success' | 'error' | 'dataLostWarning';
export interface IntegrationCredentials {
    id: string;
    credentials: any;
    crowdinId: string;
    managers?: any;
}
export interface IntegrationConfig {
    id: number;
    integrationId: string;
    crowdinId: string;
    config: any;
}
export interface IntegrationFile {
    id: string;
    name: string;
    type: SourceFilesModel.FileType;
    parentId: string;
    nodeType?: IntegrationTreeElementType;
}
export interface UpdateIntegrationRequest {
    [fileId: string]: string[];
}
export interface IntegrationRequest extends CrowdinClientRequest {
    integrationCredentials: any;
    integrationSettings?: any;
}
export interface CronJob {
    task: (projectId: number, client: Crowdin, apiCredentials: any, appRootFolder?: SourceFilesModel.Directory, config?: any) => Promise<void>;
    expression: string;
}
export interface ExtendedResult<T> {
    data?: T;
    message?: string;
    stopPagination?: boolean;
}
type LabelTreeElementType = 'primary' | 'secondary' | 'success' | 'warning' | 'info' | 'danger' | 'dark' | 'light';
export interface LabelTreeElement {
    text: string;
    type?: LabelTreeElementType;
    tooltip?: string;
    color?: string;
}
export declare enum Provider {
    CROWDIN = "crowdin",
    INTEGRATION = "integration"
}
export interface IntegrationSyncSettings {
    id: number;
    files?: any;
    integrationId: string;
    crowdinId: string;
    provider: Provider;
}
export interface IntegrationFilesSnapshot {
    id: number;
    files?: any;
    integrationId: string;
    crowdinId: string;
    provider: Provider;
}
export interface IntegrationWebhooks {
    id: number;
    fileId: number;
    integrationId: string;
    crowdinId: string;
    provider: Provider;
}
export interface SkipIntegrationNodes {
    fileNamePattern?: string;
    folderNamePattern?: string;
}
export interface Webhooks {
    crowdinWebhookUrl?: string;
    integrationWebhookUrl?: string;
    urlParam?: string;
    crowdinWebhooks?: (client: Crowdin, projectId: number, available: boolean, config?: AppSettings) => Promise<void>;
    integrationWebhooks?: (apiCredentials: any, urlParam: string, available: boolean, config?: AppSettings, syncSettings?: any) => Promise<void>;
    crowdinWebhookInterceptor?: (projectId: number, client: Crowdin, appRootFolder?: SourceFilesModel.Directory, config?: any, syncSettings?: any, webhookRequest?: any) => Promise<UpdateIntegrationRequest>;
    integrationWebhookInterceptor?: (projectId: number, client: Crowdin, apiCredentials: any, appRootFolder?: SourceFilesModel.Directory, config?: AppSettings, syncSettings?: any, webhookRequests?: any) => Promise<IntegrationFile[]>;
    queueUrl: string;
}
export declare enum SyncCondition {
    ALL = 0,
    TRANSLATED = 1,
    APPROVED = 2
}
export declare enum SyncSchedule {
    DISABLED = 0,
    ACTIVE
}
export type Payload = {
    event: string;
    projectId: string;
    language: string;
    fileId: string;
};
export type WebhookUrlParams = {
    projectId: number;
    crowdinId: string;
    clientId: string;
};
export interface UpdateCrowdinWebhookPayloadsArgs {
    integration: IntegrationLogic;
    webhookData: any;
    req: Request[];
}
export interface FilterSyncFilesArgs {
    projectId: number;
    crowdinClient: Crowdin;
    events: Payload[];
    syncFileSettings: UpdateIntegrationRequest;
    appSettings: AppSettings;
}
export interface AppSettings {
    schedule?: number;
    condition?: number;
    'new-crowdin-files'?: boolean;
    'new-integration-files'?: boolean;
    [key: string]: any;
}
interface LoginFormTokenResponse {
    access_token: string;
    expires_in: number;
    refresh_token: string;
}
export {};
