/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.openmeetings.cluster.sync;

import java.util.Iterator;

import javax.xml.namespace.QName;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.openmeetings.db.entity.server.Server;
import org.apache.openmeetings.util.OpenmeetingsVariables;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;

/**
 * 
 * Performs call to the WebService Gateway to load the server load from the
 * slave's of the cluster
 * 
 * @author sebawagner
 * 
 */
public class RestClient {

	private static final Logger log = Red5LoggerFactory.getLogger(
			RestClient.class, OpenmeetingsVariables.webAppRootKey);
	
	private enum Action {
		//kick the user from the server
		KICK_USER,
	}

	private final String host;
	private final int port;
	private final String protocol;
	private final String webapp;
	private final String user;
	private final String pass;

	private boolean loginSuccess = false;
	private String sessionId;
	
	private String publicSID;

//	private static String nameSpaceForSlaveDto = "http://room.conference.openmeetings.apache.org/xsd";
	
	private static String NAMESPACE_PREFIX = "http://services.axis.openmeetings.apache.org";

	private String getUserServiceEndPoint() {
		return protocol + "://" + host + ":" + port + "/" + webapp
				+ "/services/UserService";
	}
//
//	private String getRoomServiceEndPoint() {
//		return protocol + "://" + host + ":" + port + "/" + webapp
//				+ "/services/RoomService";
//	}

	/**
	 * The observerInstance will be notified whenever a ping was completed
	 * 
	 * @param observerInstance
	 * @param host
	 * @param port
	 * @param protocol
	 * @param webapp
	 * @param user
	 * @param pass
	 */
	public RestClient(Server server) {
		//this.server = server;
		this.host = server.getAddress();
		this.port = server.getPort();
		this.protocol = server.getProtocol();
		this.webapp = server.getWebapp();
		this.user = server.getUser();
		this.pass = server.getPass();
	}
	
	/**
	 * Main method to perform tests
	 * 
	 * @param strings
	 */
	public static void main(String... strings) {
		RestClient rClient = new RestClient("127.0.0.1", 5080, "http",
				"openmeetings", "swagner", "qweqwe");
		try {
			rClient.loginUser(Action.KICK_USER);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * for simple testing this method provides a version of the constructor
	 * without need for a server entity.<br/>
	 * <br/>
	 * There is no spring or JPA enhanced class in use here. This Object is
	 * stored in session/memory
	 * 
	 * @param host
	 * @param port
	 * @param protocol
	 * @param webapp
	 * @param user
	 * @param pass
	 */
	private RestClient(String host, int port, String protocol, String webapp,
			String user, String pass) {
		this.host = host;
		this.port = port;
		this.protocol = protocol;
		this.webapp = webapp;
		this.user = user;
		this.pass = pass;
	}

	/**
	 * compare if the details here and the one stored are still the same
	 * 
	 * @param server2
	 * @return
	 */
	public boolean hasServerDetailsChanged(Server server2) {

		if (!host.equals(server2.getAddress())) {
			return true;
		}
		if (port != server2.getPort()) {
			return true;
		}
		if (!user.equals(server2.getUser())) {
			return true;
		}
		if (!pass.equals(server2.getPass())) {
			return true;
		}
		if (!webapp.equals(server2.getWebapp())) {
			return true;
		}
		if (!protocol.equals(server2.getProtocol())) {
			return true;
		}

		return false;
	}

	/**
	 * Login the user via REST
	 * 
	 * @throws Exception
	 */
	public void loginUser(Action action) throws Exception {

		ServiceClient sender = createServiceClient(getUserServiceEndPoint());
		
		OMElement getSessionResult = sender
				.sendReceive(getPayloadMethodGetSession());
		sessionId = getSessionIdFromResult(getSessionResult);

		OMElement loginUserResult = sender
				.sendReceive(getPayloadMethodLoginUser());

		loginSuccess = loginSuccessFromResult(loginUserResult);

		switch (action) {
			case KICK_USER:
				kickUserInternl();
				break;
			default:
				throw new Exception("No action defined");
		}

	}
	
	private ServiceClient createServiceClient(String serviceEndPoint) throws Exception {
		ServiceClient sender = new ServiceClient();
		sender.engageModule(new QName(Constants.MODULE_ADDRESSING)
				.getLocalPart());
		Options options = new Options();
		options.setTo(new EndpointReference(serviceEndPoint));
		options.setProperty(Constants.Configuration.ENABLE_REST,
				Constants.VALUE_TRUE);
		int timeOutInMilliSeconds = 2000;
		// setting timeout to 2 second should be sufficient, if the server is
		// not available within the 3 second interval you got a problem anyway
		options.setTimeOutInMilliSeconds(timeOutInMilliSeconds);
		options.setProperty(HTTPConstants.SO_TIMEOUT, timeOutInMilliSeconds);
		options.setProperty(HTTPConstants.CONNECTION_TIMEOUT, timeOutInMilliSeconds);
		sender.setOptions(options);
		
		return sender;
	}
	
	private OMElement createOMElement(OMFactory fac, OMNamespace omNs, String name, String value) {
		OMElement omElement = fac.createOMElement(name, omNs);
		omElement.addChild(fac.createOMText(omElement, value));
		return omElement;
	}

	/**
	 * sets the publicSID and removes a user from a slave host by calling a REST service
	 * 
	 * @param publicSID
	 */
	public void kickUser(String publicSID) {
		this.publicSID = publicSID;
		kickUserInternl();
	}
	
	private void kickUserInternl() {
		try {
			
			if (!loginSuccess) {
				loginUser(Action.KICK_USER);
			}

			ServiceClient sender = createServiceClient(getUserServiceEndPoint());
			
			OMElement kickUserByPublicSIDResult = sender
					.sendReceive(getPayloadMethodKickUserByPublicSID());
			Boolean result = kickUserByPublicSIDFromResult(kickUserByPublicSIDResult);
			
			if (!result) {
				throw new Exception("Could not delete user from slave host");
			}

		} catch (Exception err) {
			log.error("[kickUser failed]", err);
		}
	}

	private Boolean kickUserByPublicSIDFromResult(OMElement result) throws Exception {
		QName kickUserResult = new QName(NAMESPACE_PREFIX, "return");

		@SuppressWarnings("unchecked")
		Iterator<OMElement> elements = result.getChildrenWithName(kickUserResult);
		if (elements.hasNext()) {
			OMElement resultElement = elements.next();
			if (resultElement.getText().equals("true")) {
				return true;
			} else {
				throw new Exception("Could not delete user from slave host, returns: "
						+ resultElement.getText());
			}
		} else {
			throw new Exception("Could not parse kickUserByPublicSID result");
		}
	}

	private OMElement getPayloadMethodKickUserByPublicSID() throws Exception {
		OMFactory fac = OMAbstractFactory.getOMFactory();
		OMNamespace omNs = fac.createOMNamespace(NAMESPACE_PREFIX, "pre");
		OMElement method = fac.createOMElement("kickUserByPublicSID", omNs);
		method.addChild(createOMElement(fac, omNs, "SID", sessionId));
		method.addChild(createOMElement(fac, omNs, "publicSID", publicSID));
		return method;
	}

	/**
	 * Create the REST request to get a new session Id
	 * 
	 * @return
	 */
	private OMElement getPayloadMethodGetSession() throws Exception {
		OMFactory fac = OMAbstractFactory.getOMFactory();
		OMNamespace omNs = fac.createOMNamespace(NAMESPACE_PREFIX, "pre");
		OMElement method = fac.createOMElement("getSession", omNs);
		return method;
	}

	/**
	 * Parse the session Id from the REST request
	 * 
	 * @param result
	 * @return
	 * @throws Exception
	 */
	private String getSessionIdFromResult(OMElement result) throws Exception {
		QName sessionElements = new QName(null, "session_id");

		@SuppressWarnings("unchecked")
		Iterator<OMElement> elements = result.getFirstElement()
				.getChildrenWithName(sessionElements);
		if (elements.hasNext()) {
			OMElement sessionElement = elements.next();
			return sessionElement.getText();
		} else {
			throw new Exception("Could not find session id");
		}
	}

	/**
	 * create the payload to login to another OpenMeetings instance via REST
	 * 
	 * @return
	 */
	private OMElement getPayloadMethodLoginUser() throws Exception {
		OMFactory fac = OMAbstractFactory.getOMFactory();
		OMNamespace omNs = fac.createOMNamespace(NAMESPACE_PREFIX, "pre");
		OMElement method = fac.createOMElement("loginUser", omNs);
		method.addChild(createOMElement(fac, omNs, "SID", sessionId));
		method.addChild(createOMElement(fac, omNs, "username", user));
		method.addChild(createOMElement(fac, omNs, "userpass", pass));
		return method;
	}

	/**
	 * check the result of the REST request if the login was successful
	 * 
	 * @param result
	 * @return
	 * @throws Exception
	 */
	private boolean loginSuccessFromResult(OMElement result) throws Exception {

		QName loginResult = new QName(NAMESPACE_PREFIX, "return");

		@SuppressWarnings("unchecked")
		Iterator<OMElement> elements = result.getChildrenWithName(loginResult);
		if (elements.hasNext()) {
			OMElement resultElement = elements.next();
			if (resultElement.getText().equals("1")) {
				return true;
			} else {
				throw new Exception("Could not login user at, error code is: "
						+ resultElement.getText());
			}
		} else {
			throw new Exception("Could not parse login result");
		}

	}

	/**
	 * Get and cast the element's text (if there is any)
	 * 
	 * @param resultElement
	 * @param elementName
	 * @param typeObject
	 * @return
	 */
//	private <T> T getElementTextByName(OMElement resultElement, String elementName, Class<T> typeObject) {
//		try {
//			OMElement userIdElement = resultElement
//					.getFirstChildWithName(new QName(nameSpaceForSlaveDto, elementName));
//			if (userIdElement != null && userIdElement.getText() != null
//					&& userIdElement.getText().length() > 0) {
//				
//				String defaultValue = userIdElement.getText();
//				
//				// Either this can be directly assigned or try to find a constructor
//				// that handles it
//				if (typeObject.isAssignableFrom(defaultValue.getClass())) {
//					return typeObject.cast(defaultValue);
//				}
//				Constructor<T> c = typeObject.getConstructor(defaultValue
//						.getClass());
//				return c.newInstance(defaultValue);
//				
//			}
//		} catch (Exception err) {
//			//Catch any class cast exception, but log only
//			log.error("[getElementTextByName]", err);
//		}
//		return null;
//	}
	
	
}
