/**
 * Copyright 2005-2011 Noelios Technologies.
 * 
 * The contents of this file are subject to the terms of one of the following
 * open source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL 1.0 (the
 * "Licenses"). You can select the license that you prefer but you may not use
 * this file except in compliance with one of these Licenses.
 * 
 * You can obtain a copy of the LGPL 3.0 license at
 * http://www.opensource.org/licenses/lgpl-3.0.html
 * 
 * You can obtain a copy of the LGPL 2.1 license at
 * http://www.opensource.org/licenses/lgpl-2.1.php
 * 
 * You can obtain a copy of the CDDL 1.0 license at
 * http://www.opensource.org/licenses/cddl1.php
 * 
 * You can obtain a copy of the EPL 1.0 license at
 * http://www.opensource.org/licenses/eclipse-1.0.php
 * 
 * See the Licenses for the specific language governing permissions and
 * limitations under the Licenses.
 * 
 * Alternatively, you can obtain a royalty free commercial license with less
 * limitations, transferable or non-transferable, directly at
 * http://www.noelios.com/products/restlet-engine
 * 
 * Restlet is a registered trademark of Noelios Technologies.
 */

package com.ericsson.oauthsample;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.ext.oauth.OAuthParameters;
import org.restlet.ext.oauth.OAuthProxy;
import org.restlet.resource.Finder;
import org.restlet.resource.ServerResource;
import org.restlet.routing.Filter;
import org.restlet.routing.Route;
import org.restlet.security.User;

/**
 * @author esvmart
 *
 */
public class UserCache extends Restlet {
    
    private final Map <String, User> accessTokens = new ConcurrentHashMap <String, User> ();
    private final String cookieId;
    private static final String DEFAULT_COOKIE = "_genid";
    private volatile Restlet first, second;
    
    public UserCache(){
        this(null, null, null);
    }

    public UserCache(String cookieName, Restlet first, Restlet second) {
        this.cookieId = cookieName != null ? cookieName : DEFAULT_COOKIE;
        this.first = first; this.second = second;
    }
    
    @Override
    public final void handle(Request req, Response res){
        super.handle(req, res);
        if(hasUser(req)){
            second.handle(req, res);
            return;
        }
        getLogger().info("Execute First since User is not in cache");
        res.getCookieSettings().removeAll(cookieId);
        first.handle(req, res);
        setUser(req, res);
        
    }
    
    public  boolean hasUser(Request req){
        String id = req.getCookies().getFirstValue(cookieId);
        if(id != null){
            User u = accessTokens.get(id);
            getLogger().info("Bypassing Filter since User in Cache");
            if(u != null){
                req.getClientInfo().setUser(u);
                return true;
            }
        }
        return false;
    }
    
    protected void setUser(Request req, Response res){
        User u = req.getClientInfo().getUser();
        if(u != null){
            getLogger().info("Setting cached user after handle");
            String uuid = UUID.randomUUID().toString();
            this.accessTokens.put(uuid, u);
            res.getCookieSettings().set(cookieId, uuid);
        }
    }
    
    public void setNext(boolean first, Class<? extends ServerResource> targetClass){
        setNext(first, new Finder(getContext(), targetClass));
    }
    
    public void setNext(boolean first, Restlet restlet){
        if(first)
            this.first = restlet;
        else
            this.second = restlet;
    }
    
    @Override
    public synchronized void start() throws Exception {
        if (isStopped()) {
            super.start();
            if(first != null) first.start();
            if(second != null) second.stop();
        }
    }
    
    @Override
    public synchronized void stop() throws Exception {
        if (isStarted()) {
            if(first != null) first.stop();
            if(second != null) second.stop();
            super.stop();
        }
    }
    
    


    
    
    
    
    

}
