package motoSample;

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

import java.util.logging.Logger;
import javax.inject.Inject;
import javax.faces.context.FacesContext;

import org.openid4java.discovery.DiscoveryInformation;
import org.openid4java.message.AuthRequest;
//import org.openid4java.consumer.ConsumerException;
import org.openid4java.consumer.ConsumerManager;
import org.openid4java.message.AuthRequest;
import org.openid4java.consumer.InMemoryConsumerAssociationStore;
import org.openid4java.consumer.InMemoryNonceVerifier;
import org.openid4java.message.sreg.SRegRequest;
import org.openid4java.discovery.DiscoveryException;

import java.io.IOException;
import java.util.List;

import java.util.Map;


import javax.servlet.http.HttpSession;

@ManagedBean
@RequestScoped
public class OpenIdBean implements Serializable {

    private static Logger log = Logger.getLogger(OpenIdBean.class.getName());

    @Inject
    private FacesContext context;

    private String openid;
    public void setOpenid (String openid) { this.openid = openid; }
    public String getOpenid () { return openid; }

    private static ConsumerManager consumerManager;
    public static ConsumerManager getConsumerManager() {
//        try {
            if (consumerManager == null) {
                consumerManager = new ConsumerManager();
                consumerManager.setAssociations(new InMemoryConsumerAssociationStore());
                consumerManager.setNonceVerifier(new InMemoryNonceVerifier(10000));
            }
/*        } catch (ConsumerException e) {
            String message = "Exception creating ConsumerManager!";
            log.severe(message);
            throw new RuntimeException(message, e);
        }
*/        return consumerManager;
    }

    private static DiscoveryInformation performDiscoveryOnUserSuppliedIdentifier(String userSuppliedIdentifier) {
        DiscoveryInformation ret = null;
        //
        ConsumerManager consumerManager = getConsumerManager();
        try {
        // Perform discover on the User-Supplied Identifier
        List<DiscoveryInformation> discoveries = consumerManager.discover(userSuppliedIdentifier);
        // Pass the discoveries to the associate() method...
        ret = consumerManager.associate(discoveries);

        } catch (DiscoveryException e) {
            String message = "Error occurred during discovery!";
            log.severe(message);
            throw new RuntimeException(message, e);
        }
        return ret;
    }
    
    private static AuthRequest createOpenIdAuthRequest(DiscoveryInformation discoveryInformation, String returnToUrl) {
        AuthRequest ret = null;
        //
        try {
            // Create the AuthRequest object
            ret = getConsumerManager().authenticate(discoveryInformation, returnToUrl);
            // Create the Simple Registration Request
            SRegRequest sRegRequest = SRegRequest.createFetchRequest();
            sRegRequest.addAttribute("email", false);
            sRegRequest.addAttribute("fullname", false);
            sRegRequest.addAttribute("dob", false);
            sRegRequest.addAttribute("postcode", false);
            ret.addExtension(sRegRequest);
            
        } catch (Exception e) {
            String message = "Exception occurred while building AuthRequest object!";
            log.severe(message);
            throw new RuntimeException(message, e);
        }
        return ret;
    }
    
    public void doLogin() {

        String userSuppliedIdentifier;

        Map map = context.getExternalContext().getRequestParameterMap();
        String loginTo = (String) map.get("loginTo");
        log.info("loginTo: " + loginTo);

        if (loginTo.equals("yahoo")) {
            userSuppliedIdentifier = "yahoo.co.jp";
        }
        else if (loginTo.equals("google")) {
            userSuppliedIdentifier = "https://www.google.com/accounts/o8/id";
        }
        else {
            userSuppliedIdentifier = openid;
        }
        //log.info("yahoo log in!");

        // Delegate to Open ID code
        String returnToUrl = getReturnUrl();
        /*
        */
        DiscoveryInformation discoveryInformation = performDiscoveryOnUserSuppliedIdentifier(userSuppliedIdentifier);

        //save discovery info to verify when returned.
        HttpSession session = Resources.getSession();
        session.setAttribute("discoveryInformation", discoveryInformation);

        // Create the AuthRequest
        AuthRequest authRequest = createOpenIdAuthRequest(discoveryInformation, returnToUrl);
        // Now take the AuthRequest and forward it on to the OP

        //log.info("redirect to " + authRequest.getDestinationUrl(true));
        log.info("redirecting...");
        try {
            context.getCurrentInstance().getExternalContext().redirect(authRequest.getDestinationUrl(true));
        }
        catch (IOException e) {
            log.severe("redirect exception");
        }
    }

    public static String getReturnUrl() {
        return "http://localhost:8080/moto_web_app/openIdReturn.jsf";
    }

}
