/**
 * @desc - Единый сервис для выполнения HTTP запросов. Конфигурирует запрос - установка url, метода запроса, токена и др.
 *
 * Как применять читайте в Readme.md находящимся в корне модуля или в документации. Как сгенерировать документация
 * описанно в корневом Readme.md
 *
 * Решает следующие основные задачи. Единый поток для http ошибок и фильтрация по "точки вызова api". Совершает
 * прерывание запроса по истчению таймаута. Автоматически устанавливает токен и заголовки, контролирует работу с api
 * предотвращая обращения к несуществующим url на этапе транспиляции.
 *
 * Для выполнения запросов использует конфигурационный файл. В конфигурационном файле указывается домен с которым
 * должен работать API и список доступных ссылок(роутов), а так же другие параметры.
 *
 * Архитектура:
 * 1. В основе модуля лежит идея - сервис получения данных, например данных о погоде, должен только получать данные, но
 * не определять из какого источника будут получены данные. т.е. идея разделения обязанностей 1. конфигурирование
 * конкретного запроса и 2. конфигурирование работы с конкретным api (доменом) в целом.
 * т.е. сервис получает данные по погоде, а откуда он их получит определяется в конфигурации и используя разные
 * конфигурации (config файлы) один и тот же код сервиса сможет загружать данные из разных истоников нечего не зная о них.
 * */
import { InjectionToken } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from "@angular/common/http";
import { ISApi } from './typings';
import { TokenService } from './token.service';
import { LoadingStreamService } from './loading-stream.service';
import { ErrorsStreamService } from "./errors-stream.service";
import { Observable } from "rxjs/Observable";
import 'rxjs/add/observable/of';
/**
 * Мысли по поводу кеширования запросов:
 *
 * Что у нас есть?
 * Есть метод получающий ключ по которому можно проверить значение в хранилище.
 *
 * У нас есть запросы которые нужно кэшировать, а есть которые нет. т.е. методы.
 * GET запросы мы кэшируем. потому что мы получаем данные
 * POST, PUT, PATCH запросы мы кэшировать не можем так как они изменяют данные
 * итого кэшируются только GET запросы.
 * Нужно иметь глобальный флаг в конфигурации cache
 * а для каждого отдельно взятого запроса нужно иметь возможность
 * в конфиге опциях запроса нужно учесть флаг освежения запроса. если он true то в любом случае выполнить http запрос
 *
 * Нужно поработать с объектом типа storage. Создать ему еидный интерфей. продумать переключение между разными
 * хранилищами.
 *
 * У нас много хранилищь и конфигураций. При декларировании провайдера мы должны определить как именно будет создаваться
 * экземпляр класса ApiService и сделать это таким образом, чтоб эземпляру были переданы все нужные конфигурации путей
 * http и все возможные типы хранилищь из которых api.service сможет доставать данные.
 * Для обращения к хранилищу используем метод lookInStorage который посмотрит в конфигурации имя хранилища к которому
 * нужно обратиться за данными и выполнит обращение. Полученные данные вернет наружу.
 *
 * Если мы кэшируем какой лиюо get запрос то может возникнуть ситуация когда POST запросом или PATCH запросом данные
 * были изменены. В данной ситуации в кэше окажутся устаревшие данные. Нужно предусмотреть стратегию которая решит
 * данную проблему.
 * */
export declare const API_CONFIG: InjectionToken<{}>;
export declare const API_SERVICE: InjectionToken<{}>;
export declare class ApiService {
    private http;
    private token;
    private errors;
    private loading;
    apiConfigs: any;
    protected _defaultField: string;
    storages: ISApi.storages;
    configs: ISApi.configs;
    constructor(http: HttpClient, token: TokenService, errors: ErrorsStreamService, loading: LoadingStreamService, apiConfigs: any);
    /**
     * @desc - получить конфигурацию по имени
     * */
    getConfig<T>(name: string): T;
    /**
     * @desc - Задает конфигурацию которая будет использована для выполнения http запроса. Любой http запрос начинается с
     * этого метода.
     * */
    useConfig<T>(name: string): {
        request: (cb: (config: T) => ISApi.apiRequestOptions<HttpHeaders, HttpParams>) => {
            stream: <T>() => Observable<T>;
            promise: <T>() => Promise<T>;
        };
    };
    /**
     * @desc - конфигурирует http запрос. устанавливает url, заголовки, токен параметры и т.д.
     * */
    private request2(apiOptions);
    /**
     * @desc - определяет какой метод (get, post и т.д.) нужно вызывать исходя из конфигурации
     * */
    private doRequest(apiOptions);
    /**
     * @desc - навешивает на http запрос функции общие для любого запроса. Генерация потока ошибок, потока загрузок
     * и таймаут запроса. Сюда можно добавить кэширование, повторные запросы при неудаче и др.
     * */
    private getStartLoadingWrapper(request, apiOptions);
    /**
     * @desc - закодирует параметры get запроса. !!знак '+' нужно кодировать отдельно иначе возникнет ошибка!!
     * */
    private encodeURL(url, paramsArray, config);
    /**
     * @desc - проверяет уловия при которых можно отдавать закэшированное значение и если уловия верны возвращает кэш.
     * */
    private checkConditionsAndGetCache(apiOptions);
    /**
     * @desc - Для обращения к хранилищу используем метод lookInStorage который посмотрит в конфигурации имя хранилища
     * к которому нужно обратиться за данными и выполнит обращение. Полученные данные вернет наружу.
     * */
    private lookInStorage(key, storage?);
    /**
     * @desc - Используя базовый url и набор GET параметров запроса формирует имя ключа для сохранения и получения
     * закэшированных данных для данного url.
     * */
    private getKey<T>(baseURL, params, exclude?);
}
