//   Copyright 2012 Georg-August-Universität Göttingen, Germany
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package de.ugoe.cs.autoquest.httpmonitor.proxy;

import java.util.logging.Level;

import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.api.Response.CompleteListener;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion;

import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorComponent;
import de.ugoe.cs.autoquest.httpmonitor.HttpMonitorException;
import de.ugoe.cs.autoquest.httpmonitor.IdGenerator;
import de.ugoe.cs.autoquest.httpmonitor.SimpleIdGenerator;
import de.ugoe.cs.util.console.Console;

/**
 * <p>
 * if a central monitoring server is used by the proxy, then this id generator is a connection to
 * the server to receive centrally unique ordering ids from the central server. If the central
 * server cannot be reached, this id generated uses a fallback internal {@link SimpleIdGenerator}.
 * </p>
 * 
 * @author Patrick Harms
 */
public class HttpMonitorRemoteIdGenerator
    extends HttpMonitorRemoteConnection
    implements CompleteListener, IdGenerator, HttpMonitorComponent
{
    /** the fall back id generator used internally if the server is not reachable*/
    private IdGenerator fallBackIdGenerator = new SimpleIdGenerator();
    
    /**
     * <p>
     * initializes the id generator with the host and port of the central server from which to
     * retrieve the ids
     * </p>
     *
     * @param httpMonitorServer the host name of the central server
     * @param httpMonitorPort   the port of the central server
     */
    public HttpMonitorRemoteIdGenerator(String httpMonitorServer, int httpMonitorPort) {
        super(httpMonitorServer, httpMonitorPort);
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.httpmonitor.proxy.HttpMonitorRemoteConnection#init()
     */
    @Override
    public void init() throws IllegalStateException, HttpMonitorException {
        fallBackIdGenerator.init();
        super.init();
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.httpmonitor.proxy.HttpMonitorRemoteConnection#start()
     */
    @Override
    public void start() throws IllegalStateException, HttpMonitorException {
        fallBackIdGenerator.start();
        super.start();
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.httpmonitor.proxy.HttpMonitorRemoteConnection#stop()
     */
    @Override
    public void stop() {
        super.stop();
        fallBackIdGenerator.stop();
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.httpmonitor.IdGenerator#getNextId()
     */
    @Override
    public synchronized long getNextId() {
        Request httpMonitorRequest = super.newRequest();
        httpMonitorRequest.method(HttpMethod.GET);
        httpMonitorRequest.version(HttpVersion.HTTP_1_1);
        super.sendRequest(httpMonitorRequest);

        Result result = super.getResult(httpMonitorRequest);
        
        if (result.isFailed()) {
            Console.traceln
                (Level.WARNING, "could not retrieve next id correctly: " + result.getFailure());
            Console.logException((Exception) result.getFailure());
            
            Console.traceln(Level.WARNING, "using fallback, i.e., internal id generator");
            return fallBackIdGenerator.getNextId();
        }
        else {
            try {
                return result.getResponse().getHeaders().getLongField("X-AutoQUEST-OrderingId");
            }
            catch (NumberFormatException e) {
                Console.traceln(Level.WARNING, "could not retrieve next id correctly: " + e);
                Console.logException(e);
                
                Console.traceln(Level.WARNING, "using fallback, i.e., internal id generator");
                return fallBackIdGenerator.getNextId();
            }
        }
        
    }

}
