import axios, { AxiosRequestHeaders } from 'axios';
import Config                         from '../config/Config';
import SessionManager                 from './SessionManager';
import FormData                       from 'form-data';
import logger                         from '../shared/logging/WinstonLogger';
import GitlabManager                  from './GitlabManager';


class HttpManager {
    private _API_BASE_URL!: string;
    public LOGIN_URL!: string;
    public TEST_SESSION_URL!: string;

    public handleCommandErrors: boolean = true;

    private static _instance: HttpManager;

    public static get instance(): HttpManager {
        if ( !HttpManager._instance ) {
            HttpManager._instance = new HttpManager();
        }

        return HttpManager._instance;
    }

    private constructor() {

    }

    set API_BASE_URL(url: string) {
        this._API_BASE_URL = url;

        this.LOGIN_URL = `${ this._API_BASE_URL }/login`;
        this.TEST_SESSION_URL = `${ this._API_BASE_URL }/test_session`;
    }

    registerAxiosInterceptor() {
        this.registerRequestInterceptor();
        this.registerResponseInterceptor();
    }

    private registerRequestInterceptor() {
        axios.interceptors.request.use((config) => {
            if ( config.data instanceof FormData ) {
                config.headers = { ...config.headers, ...(config.data as FormData).getHeaders() } as AxiosRequestHeaders;
            }

            if ( SessionManager.isLogged && config.url && config.url.indexOf(Config.apiURL) !== -1 ) {
                config.headers.Authorization = 'Bearer ' + SessionManager.token;
            }

            if ( GitlabManager.isLogged && config.url && config.url.indexOf(Config.gitlab.apiURL) !== -1 ) {
                config.headers['PRIVATE-TOKEN'] = GitlabManager.token;
            }

            return config;
        });
    }

    private registerResponseInterceptor() {
        axios.interceptors.response.use((response) => {

            if ( response.data && response.data.sessionToken ) {
                SessionManager.token = response.data.sessionToken;
            }

            return response;
        }, (error) => {
            if ( error.response ) {
                if ( this.handleCommandErrors ) {
                    if ( error.response.url && error.response.url.indexOf(Config.apiURL) !== -1 ) {
                        switch ( error.response.status ) {
                            case 401:   // Unauthorized
                                logger.error('Session expired or inexistent. Please login again.');
                                process.exit(1);
                                break;
                            case 403:   // Forbidden
                                logger.error('Forbidden access.');
                                process.exit(1);
                                break;
                        }
                    }
                } else {
                    this.handleCommandErrors = true;
                }
            } else {
                logger.error('Error connecting to the server.');
                process.exit(1);
            }


            return Promise.reject(error);
        });
    }
}


export default HttpManager.instance;