import * as _themost_common from '@themost/common';
import { ApplicationService, ApplicationBase, ConfigurationStrategy, ConfigurationBase } from '@themost/common';
import { Router, Application, Handler, Request as Request$1 } from 'express';
import { Store, Options } from 'express-rate-limit';
import { BehaviorSubject } from 'rxjs';
import { Store as Store$1, Options as Options$1 } from 'express-slow-down';
import RedisStore from 'rate-limit-redis';
import { DataContext } from '@themost/data';

declare type RateLimitStoreConstructor = new (...arg: unknown[]) => Store;

declare interface RateLimitServiceConfiguration {
    extends?: string;
    storeType?: string;
    profiles?: [string, Options][];
    paths?: [string, ({ profile: string } | Options)][];
}

declare class RateLimitService extends ApplicationService {
    constructor(app: _themost_common.ApplicationBase);
    readonly loaded: BehaviorSubject<Router>;
    getServiceContainer(): BehaviorSubject<Router | Application>;
    getServiceName(): string;
    getServiceConfiguration(): RateLimitServiceConfiguration;
    set(path: string, options: { profile?: string } | Options): this;
    unset(path: string): this;
}

declare type SpeedLimitStoreConstructor = new (...arg: unknown[]) => Store$1;

declare interface SpeedLimitServiceConfiguration {
    extends?: string;
    storeType?: string;
    profiles?: Map<string, Options$1>;
    paths?: Map<string, ({ profile: string } | Options$1)>;
}

declare class SpeedLimitService extends ApplicationService {
    constructor(app: ApplicationBase);
    getServiceContainer(): BehaviorSubject<Router | Application>;
    getServiceName(): string;
    getServiceConfiguration(): SpeedLimitServiceConfiguration;
    set(path: string, options: { profile?: string } | Options$1): this;
    unset(path: string): this;
}

declare class RedisClientStore extends RedisStore {
    constructor(app: ApplicationService);
}

/**
 * @license
 * Universis Project Version 1.0
 * Copyright (c) 2018, Universis Project All rights reserved
 *
 * Use of this source code is governed by an LGPL 3.0 license that can be
 * found in the LICENSE file at https://universis.io/license
 */


declare class ScopeString {
    constructor(str: string);
    split(): string[];
}

declare interface UniversisConfigurationSection {
    universis: {
        [k: string]: any;
    }
}

declare interface ScopeAccessConfigurationSection {
    janitor: {
        scopeAccess: {
            imports: string[]
        }
    }
}

/**
 * Declares a configuration element for managing scope-based permissions on server resources
 */
declare interface ScopeAccessConfigurationElement {
    /**
     * Gets or sets an array of strings that holds an array of scopes e.g. students or students:read or students,teachers etc
     */
    scope: string[],
    /**
     * Gets or sets a string which represents the regular expression that is going to be used for validating endpoint
     */
    resource: string;
    /**
     * Gets or sets an array of strings which represents the access levels for the given scopes e.g. READ or READ,WRITE etc
     */
    access: string[];
    /**
     * Gets or sets a string which represents a short description for this item
     */
    description?: string;
}

declare class ScopeAccessConfiguration extends ConfigurationStrategy {

    constructor(configuration: ConfigurationBase);

    /**
     * Gets an array of scope access configuration elements
     */
    public elements: ScopeAccessConfigurationElement[];

    /**
     * Verifies the given request and returns a promise that resolves with a scope access configuration element
     */
    verify(req: Request): Promise<ScopeAccessConfigurationElement>;
}

declare class DefaultScopeAccessConfiguration extends ScopeAccessConfiguration {

    constructor(configuration: ConfigurationBase);
    /**
     * Gets an array of scope access configuration elements
     */
    public elements: ScopeAccessConfigurationElement[];
    /**
     * Verifies the given request and returns a promise that resolves with a scope access configuration element
     */
    verify(req: Request): Promise<ScopeAccessConfigurationElement>;

}

declare class EnableScopeAccessConfiguration extends ApplicationService {
    constructor(app: ApplicationBase);
}

declare class ExtendScopeAccessConfiguration extends ApplicationService {
    constructor(app: ApplicationBase);
}

declare function validateScope(): Handler;

declare interface OAuth2MethodOptions {
    access_token: string;
}

declare interface OAuth2AuthorizeUser {
    client_id?: string;
    client_secret?: string;
    username: string;
    password: string;
    grant_type: string;
    scope?: string;
}

declare interface OAuth2ServiceSettings {
    unattendedExecutionAccount?: string;
    client_id: string;
    client_secret?: string;
    server_uri: string;
    userinfo_uri?: string;
    introspect_uri?: string;
    admin_uri?: string;
    well_known_configuration_uri?: string;
    adminAccount: {
        username: string;
        password: string;
        client_id: string;
        client_secret?: string;
        scope?: string;
    }
}

declare interface OAuth2UserProfile {
    sub: string;
    name: string;
    preferred_username: string;
    given_name: string;
    family_name: string;
    email: string;
}

declare interface GenericUser {
     id?: any; 
     additionalType?: string; 
     alternateName?: string; 
     description?: string; 
     givenName?: string; 
     familyName?: string; 
     image?: string; 
     name?: string; 
     url?: string; 
     dateCreated?: Date; 
     dateModified?: Date; 
     createdBy?: any; 
     modifiedBy?: any; 
     lockoutTime?: Date; 
     logonCount?: number; 
     enabled?: boolean; 
     lastLogon?: Date; 
     userCredentials?: {
         userPassword?: string;
         userActivated?: boolean;
         temporary?: boolean;
     }
}

declare interface OAuth2User {
    id?: any; 
    username?: string; 
    email?: string; 
    enabled?: boolean;
    emailVerified?: boolean;
    firstName?: string; 
    lastName?: string; 
    credentials?: {
        algorithm?: string,
        temporary?: boolean,
        type?: string,
        value?: string
    }
}

declare class OAuth2ClientService extends ApplicationService {
    get settings(): OAuth2ServiceSettings;
    constructor(app: ApplicationBase)
    getUserInfo(context: DataContext, token: string): Promise<OAuth2UserProfile>;
    getTokenInfo(context: DataContext, token: string): Promise<any>;
    getContextTokenInfo(context: DataContext): Promise<any>;
    authorize(authorizeUser: OAuth2AuthorizeUser): Promise<{ access_token?: string, refresh_token?: string}>;
    getUser(username: string, options: OAuth2MethodOptions): Promise<any>;
    getUserById(user_id: any, options: OAuth2MethodOptions): Promise<any>;
    getUserByEmail(email: string, options: OAuth2MethodOptions): Promise<any>;
    updateUser(user: GenericUser | any, options: OAuth2MethodOptions): Promise<any>;
    createUser(user: GenericUser | any, options: OAuth2MethodOptions): Promise<any>;
    deleteUser(user: { id: any }, options: OAuth2MethodOptions): Promise<any>; 
}

declare class RemoteAddressValidator extends ApplicationService {
    
    constructor(app: ApplicationService);
    validateRemoteAddress(request: Request$1): Promise<boolean>;
    getRemoteAddress(request: Request$1): string;

}

declare class AppRateLimitService extends RateLimitService {
    constructor(app: _themost_common.ApplicationBase);
}

declare class AppSpeedLimitService extends SpeedLimitService {
    constructor(app: _themost_common.ApplicationBase);
}

export { AppRateLimitService, AppSpeedLimitService, DefaultScopeAccessConfiguration, EnableScopeAccessConfiguration, ExtendScopeAccessConfiguration, OAuth2ClientService, RateLimitService, RedisClientStore, RemoteAddressValidator, ScopeAccessConfiguration, ScopeString, SpeedLimitService, validateScope };
export type { GenericUser, OAuth2AuthorizeUser, OAuth2MethodOptions, OAuth2ServiceSettings, OAuth2User, OAuth2UserProfile, RateLimitServiceConfiguration, RateLimitStoreConstructor, ScopeAccessConfigurationElement, ScopeAccessConfigurationSection, SpeedLimitServiceConfiguration, SpeedLimitStoreConstructor, UniversisConfigurationSection };
