package eu.eudat.logic.security.validators;

import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
import eu.eudat.logic.security.customproviders.B2Access.B2AccessCustomProvider;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.ConfigurableProviderCustomProvider;
import eu.eudat.logic.security.customproviders.LinkedIn.LinkedInCustomProvider;
import eu.eudat.logic.security.customproviders.ORCID.ORCIDCustomProvider;
import eu.eudat.logic.security.customproviders.OpenAIRE.OpenAIRECustomProvider;
import eu.eudat.logic.security.customproviders.Zenodo.ZenodoCustomProvider;
import eu.eudat.logic.security.validators.b2access.B2AccessTokenValidator;
import eu.eudat.logic.security.validators.configurableProvider.ConfigurableProviderTokenValidator;
import eu.eudat.logic.security.validators.facebook.FacebookTokenValidator;
import eu.eudat.logic.security.validators.google.GoogleTokenValidator;
import eu.eudat.logic.security.validators.linkedin.LinkedInTokenValidator;
import eu.eudat.logic.security.validators.openaire.OpenAIRETokenValidator;
import eu.eudat.logic.security.validators.orcid.ORCIDTokenValidator;
import eu.eudat.logic.security.validators.twitter.TwitterTokenValidator;
import eu.eudat.logic.security.validators.zenodo.ZenodoTokenValidator;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;


@Service("tokenValidatorFactory")
public class TokenValidatorFactoryImpl implements TokenValidatorFactory {
    public enum LoginProvider {
        GOOGLE(1), FACEBOOK(2), TWITTER(3), LINKEDIN(4), NATIVELOGIN(5), B2_ACCESS(6), ORCID(7), OPENAIRE(8), CONFIGURABLE(9), ZENODO(10);

        private int value;

        private LoginProvider(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public static LoginProvider fromInteger(int value) {
            switch (value) {
                case 1:
                    return GOOGLE;
                case 2:
                    return FACEBOOK;
                case 3:
                    return TWITTER;
                case 4:
                    return LINKEDIN;
                case 5:
                    return NATIVELOGIN;
                case 6:
                    return B2_ACCESS;
                case 7:
                    return ORCID;
                case 8:
                    return OPENAIRE;
                case 9:
                    return CONFIGURABLE;
                case 10:
                    return ZENODO;
                default:
                    throw new RuntimeException("Unsupported LoginProvider");
            }
        }
    }

    private Environment environment;
    private AuthenticationService nonVerifiedUserAuthenticationService;
    private B2AccessCustomProvider b2AccessCustomProvider;
    private ORCIDCustomProvider orcidCustomProvider;
    private LinkedInCustomProvider linkedInCustomProvider;
    private OpenAIRECustomProvider openAIRECustomProvider;
    private ConfigurableProviderCustomProvider configurableProviderCustomProvider;
    private ConfigLoader configLoader;
    private ZenodoCustomProvider zenodoCustomProvider;

    @Autowired
    public TokenValidatorFactoryImpl(
            Environment environment,
            AuthenticationService nonVerifiedUserAuthenticationService, B2AccessCustomProvider b2AccessCustomProvider,
            ORCIDCustomProvider orcidCustomProvider, LinkedInCustomProvider linkedInCustomProvider, OpenAIRECustomProvider openAIRECustomProvider,
            ConfigurableProviderCustomProvider configurableProviderCustomProvider, ConfigLoader configLoader,
            ZenodoCustomProvider zenodoCustomProvider) {
        this.environment = environment;
        this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
        this.b2AccessCustomProvider = b2AccessCustomProvider;
        this.orcidCustomProvider = orcidCustomProvider;
        this.linkedInCustomProvider = linkedInCustomProvider;
        this.openAIRECustomProvider = openAIRECustomProvider;
        this.configurableProviderCustomProvider = configurableProviderCustomProvider;
        this.configLoader = configLoader;
        this.zenodoCustomProvider = zenodoCustomProvider;
    }

    public TokenValidator getProvider(LoginProvider provider) {
        switch (provider) {
            case GOOGLE:
                return new GoogleTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService);
            case FACEBOOK:
                return new FacebookTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService);
            case LINKEDIN:
                return new LinkedInTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService, linkedInCustomProvider);
            case TWITTER:
                return new TwitterTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService);
            case B2_ACCESS:
                return new B2AccessTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService, this.b2AccessCustomProvider);
            case ORCID:
                return new ORCIDTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService, this.orcidCustomProvider);
            case OPENAIRE:
                return new OpenAIRETokenValidator(this.environment, this.nonVerifiedUserAuthenticationService, this.openAIRECustomProvider);
            case CONFIGURABLE:
                return new ConfigurableProviderTokenValidator(this.configurableProviderCustomProvider, this.nonVerifiedUserAuthenticationService, this.configLoader);
            case ZENODO:
                return new ZenodoTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService, this.zenodoCustomProvider);
            default:
                throw new RuntimeException("Login Provider Not Implemented");
        }
    }
}
