/*
 * Copyright (c) eHealth
 */
package be.fgov.ehealth.technicalconnector.tests.junit.rule;

import java.io.IOException;
import java.util.Properties;

import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.exception.TechnicalConnectorExceptionValues;
import be.ehealth.technicalconnector.utils.ConnectorIOUtils;
import org.apache.commons.collections.functors.ExceptionClosure;
import org.apache.commons.lang.Validate;
import org.junit.rules.ExternalResource;

import be.fgov.ehealth.technicalconnector.tests.session.SessionDestroyer;
import be.fgov.ehealth.technicalconnector.tests.session.SessionInitializer;
import be.fgov.ehealth.technicalconnector.tests.utils.LoggingUtils;
import be.fgov.ehealth.technicalconnector.tests.utils.SupportedLanguages;

/**
 * @author EHP
 */
public class SessionRule extends ExternalResource {

    public static EnvironmentSelectorStep withActiveSession() {
        return new InnerStep(true);
    }

    public static EnvironmentSelectorStep withInactiveSession() {
        return new InnerStep(false);
    }

    public static interface EnvironmentSelectorStep extends BuilderStep {

        ProfessionSelectorStep forEnvironment(String env);

        BuilderStep baseOn(String location);
    }

    public static interface ProfessionSelectorStep {

        UserSelectorStep forProfession(String prof);
    }

    public static interface UserSelectorStep {

        ProgramLangStep forUser(String env);
    }

    public static interface ProgramLangStep extends BuilderStep {

        BuilderStep forProgrammingLanguage(SupportedLanguages lang);
    }

    public static interface BuilderStep {

        SessionRule build();
    }


    private static class InnerStep implements EnvironmentSelectorStep, ProfessionSelectorStep, UserSelectorStep, ProgramLangStep {

        private boolean activate;

        private SupportedLanguages lang = SupportedLanguages.JAVA;

        private Properties props = new Properties();

        private InnerStep(boolean activeSession) {
            this.activate = activeSession;
        }

        @Override
        public BuilderStep baseOn(String location) {
            Validate.notEmpty(location);
            try {
                props.load(ConnectorIOUtils.getResourceAsStream(location));
            } catch (Exception e) {
                throw new IllegalArgumentException(e);
            }
            return this;
        }

        @Override
        public BuilderStep forProgrammingLanguage(SupportedLanguages lang) {
            this.lang = lang;
            return this;
        }

        @Override
        public ProgramLangStep forUser(String user) {
            Validate.notEmpty(user);
            props.setProperty(SessionInitializer.SESSION_USERNAME, user);
            return this;
        }

        @Override
        public UserSelectorStep forProfession(String prof) {
            Validate.notEmpty(prof);
            props.setProperty(SessionInitializer.SESSION_PROFESSION_TYPE, prof);
            return this;
        }

        @Override
        public ProfessionSelectorStep forEnvironment(String env) {
            Validate.notEmpty(env);
            props.setProperty(SessionInitializer.SESSION_ENVIRONMENT, env);
            return this;
        }

        @Override
        public SessionRule build() {
            LoggingUtils.bootstrap();
            return new SessionRule(props, activate, lang);
        }

    }

    private Properties props;

    private boolean activate;

    private SupportedLanguages devLang;

    private SessionRule(Properties props, boolean activate, SupportedLanguages devLang) {
        this.props = props;
        this.activate = activate;
        this.devLang = devLang;
    }


    @Override
    protected void before() throws Throwable {
        SessionInitializer.init(props, activate, devLang.getAbbreviation());
    }


    @Override
    protected void after() {
        try {
            SessionDestroyer.destroy();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    public String getSessionProperty(String key) {
        return SessionInitializer.getSessionProps().getProperty(key);
    }

}
