/*
 * 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.web.pages.auth;

import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_FRONTEND_REGISTER_KEY;
import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_IGNORE_BAD_SSL;
import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
import static org.apache.openmeetings.web.app.Application.getBean;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.io.IOUtils;
import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
import org.apache.openmeetings.db.dao.server.OAuth2Dao;
import org.apache.openmeetings.db.dao.user.OrganisationDao;
import org.apache.openmeetings.db.dao.user.UserDao;
import org.apache.openmeetings.db.entity.server.OAuthServer;
import org.apache.openmeetings.db.entity.user.Organisation_Users;
import org.apache.openmeetings.db.entity.user.User;
import org.apache.openmeetings.db.entity.user.User.Right;
import org.apache.openmeetings.db.entity.user.User.Type;
import org.apache.openmeetings.web.app.Application;
import org.apache.openmeetings.web.app.WebSession;
import org.apache.openmeetings.web.pages.BaseInitedPage;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.json.JSONException;
import org.apache.wicket.ajax.json.JSONObject;
import org.apache.wicket.markup.head.CssContentHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.request.IRequestParameters;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.flow.RedirectToUrlException;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.string.StringValue;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;

public class SignInPage extends BaseInitedPage {
	private static final long serialVersionUID = 1L;
	private static final Logger log = Red5LoggerFactory.getLogger(SignInPage.class, webAppRootKey);
	private SignInDialog d;
	
	static boolean allowRegister() {
		return "1".equals(getBean(ConfigurationDao.class).getConfValue(CONFIG_FRONTEND_REGISTER_KEY, String.class, "0"));
	}
	
	static boolean allowOAuthLogin() {
		return getBean(OAuth2Dao.class).getActive().size() > 0;
	}
	
	public SignInPage(PageParameters p) {
		super();
		StringValue oauthid = p.get("oauthid");
		if (!oauthid.isEmpty()) { // oauth2 login
			try {
				long serverId = oauthid.toLong(-1);
				OAuthServer server = getBean(OAuth2Dao.class).get(serverId);
				log.debug("OAuthServer=" + server);
				if (server == null) {
					log.warn("OAuth server id=" + serverId + " not found");
					return;
				}
				
				if (p.get("code").toString() != null) { // got code
					String code = p.get("code").toString();
					log.debug("OAuth response code=" + code);
				 	AuthInfo authInfo = getToken(code, server);
				 	if (authInfo == null) return;
				 	log.debug("OAuthInfo=" + authInfo);
				 	Map<String, String> authParams = getAuthParams(authInfo.accessToken, code, server);
				 	if (authParams != null) {
				 		loginViaOAuth2(authParams, serverId);
				 	}
				} else { // redirect to get code
					String redirectUrl = prepareUrlParams(server.getRequestKeyUrl(), server.getClientId(), 
							null, null, getRedirectUri(server, this), null);
					log.debug("redirectUrl=" + redirectUrl);
					throw new RedirectToUrlException(redirectUrl);
				}
			} catch (IOException e) {
				log.error("OAuth2 login error", e);
			} catch (NoSuchAlgorithmException e) {
				log.error("OAuth2 login error", e);
			}
		}
		//will try to login directly using parameters sent by POST
		IRequestParameters pp = RequestCycle.get().getRequest().getPostParameters();
		StringValue login = pp.getParameterValue("login"), password = pp.getParameterValue("password");
		if (!login.isEmpty() && !password.isEmpty()) {
			if (WebSession.get().signIn(login.toString(), password.toString(), Type.user, null)) {
	 			setResponsePage(Application.get().getHomePage());
			} else {
				log.error("Failed to login using POST parameters passed");
			}
		}
		
		RegisterDialog r = new RegisterDialog("register");
		ForgetPasswordDialog f = new ForgetPasswordDialog("forget");
		d = new SignInDialog("signin");
		d.setRegisterDialog(r);
		d.setForgetPasswordDialog(f);
		r.setSignInDialog(d);
		f.setSignInDialog(d);
		add(d, r.setVisible(allowRegister()), f);
	}
	
	public SignInPage() {
		this(new PageParameters());
	}
	
	@Override
	public void renderHead(IHeaderResponse response) {
		super.renderHead(response);
		//TODO need to be removed if autoOen will be enabled
		response.render(OnDomReadyHeaderItem.forScript("$('#" + d.getMarkupId() + "').dialog('open');"));
		response.render(new CssContentHeaderItem(".no-close .ui-dialog-titlebar-close { display: none; }", "dialog-noclose", ""));
	}
	
	@Override
	protected void onParameterArrival(IRequestParameters params, AjaxRequestTarget arg1) {
		WebSession.get().setArea(getUrlFragment(params));
	}
	
	// ============= OAuth2 methods =============
		
	public String prepareUrlParams(String urlTemplate, String clientId, String clientSecret, 
			String clientToken, String redirectUri, String code) throws UnsupportedEncodingException {
		String result = urlTemplate;
		if (clientId != null) {
			result = result.replace("{$client_id}", clientId);
		}
		if (clientSecret != null) {
			result = result.replace("{$client_secret}", clientSecret);
		}
		if (clientToken != null) {
			result = result.replace("{$access_token}", clientToken);
		}
		if (redirectUri != null) {
			result = result.replace("{$redirect_uri}", URLEncoder.encode(redirectUri, "UTF-8"));
		}
		if (code != null) {
			result = result.replace("{$code}", code);
		}
		return result;
	}
		
	public static String getRedirectUri(OAuthServer server, Component component) {
		String result = "";
		try {
			String base = getBean(ConfigurationDao.class).getBaseUrl();
			URI uri = new URI(base + component.urlFor(SignInPage.class, new PageParameters().add("oauthid", server.getId())));
			result = uri.normalize().toString();
		} catch (URISyntaxException e) {
			log.error("Unexpected error while getting redirect URL", e);
		}
		return result;
	}
		
	private void prepareConnection(URLConnection connection) {
		if (!(connection instanceof HttpsURLConnection)) return;
		ConfigurationDao configurationDao = getBean(ConfigurationDao.class);
		Boolean ignoreBadSSL = configurationDao.getConfValue(CONFIG_IGNORE_BAD_SSL, String.class, "no").equals("yes");
		if (!ignoreBadSSL) return;
		TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
			public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
			public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
				
	    } };
		try {
			SSLContext sslContext = SSLContext.getInstance("SSL");
			sslContext.init( null, trustAllCerts, new java.security.SecureRandom() );
		    SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
			((HttpsURLConnection) connection).setSSLSocketFactory(sslSocketFactory);
			((HttpsURLConnection) connection).setHostnameVerifier(new HostnameVerifier() {
					
				public boolean verify(String arg0, SSLSession arg1) {
					return true;
				}
					
			});
		} catch (Exception e) {
			log.error("[prepareConnection]", e);
		}
	}
		
	private AuthInfo getToken(String code, OAuthServer server) throws IOException {
		String requestTokenBaseUrl = server.getRequestTokenUrl();
		// build url params to request auth token
		String requestTokenParams = server.getRequestTokenAttributes();
		requestTokenParams = prepareUrlParams(requestTokenParams, server.getClientId(), server.getClientSecret(), 
				null, getRedirectUri(server, this), code);
		// request auth token
		HttpURLConnection urlConnection = (HttpURLConnection) new URL(requestTokenBaseUrl).openConnection();
		prepareConnection(urlConnection);
		urlConnection.setRequestMethod("POST");
		urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
		urlConnection.setRequestProperty("charset", "utf-8");
		urlConnection.setRequestProperty("Content-Length", String.valueOf(requestTokenParams.length()));
		urlConnection.setDoInput(true);
		urlConnection.setDoOutput(true);
		urlConnection.setUseCaches(false);
		DataOutputStream paramsOutputStream = new DataOutputStream(urlConnection.getOutputStream());
		paramsOutputStream.writeBytes(requestTokenParams);
		paramsOutputStream.flush();
		String sourceResponse = IOUtils.toString(urlConnection.getInputStream(), "utf-8");
		// parse json result
		AuthInfo result = new AuthInfo();
		try {
			JSONObject jsonResult = new JSONObject(sourceResponse.toString());
			if (jsonResult.has("access_token")) {
				result.accessToken = jsonResult.getString("access_token");
			}
			if (jsonResult.has("refresh_token")) {
				result.refreshToken = jsonResult.getString("refresh_token");
			}
			if (jsonResult.has("token_type")) {
				result.tokenType = jsonResult.getString("token_type");
			}
			if (jsonResult.has("expires_in")) {
				result.expiresIn = jsonResult.getLong("expires_in");
			}
		} catch (JSONException e) {
			// try to parse as canonical
			Map<String, String> parsedMap = parseCanonicalResponse(sourceResponse.toString());
			result.accessToken = parsedMap.get("access_token");
			result.refreshToken = parsedMap.get("refresh_token");
			result.tokenType = parsedMap.get("token_type");
			try {
				result.expiresIn = Long.valueOf(parsedMap.get("expires_in"));
			} catch (NumberFormatException nfe) {}
		}
		// access token must be specified
		if (result.accessToken == null) {
			log.error("Response doesn't contain access_token field:\n" + sourceResponse.toString());
			return null;
		}
		return result;
	}
	
	private Map<String, String> parseCanonicalResponse(String response) {
		String[] parts = response.split("&");
		Map<String, String> result = new HashMap<String, String>();
		for (String part: parts) {
			String pair[] = part.split("=");
			if (pair.length > 1) {
				result.put(pair[0], pair[1]);
			}
		}
		return result;
	}
	
	private Map<String, String> getAuthParams(String token, String code, OAuthServer server) throws IOException {
		// get attributes names
		String loginAttributeName = server.getLoginParamName();
		String emailAttributeName = server.getEmailParamName();
		String firstname = server.getFirstnameParamName();
		String lastname = server.getLastnameParamName();
		// prepare url
		String requestInfoUrl = server.getRequestInfoUrl();
		requestInfoUrl = prepareUrlParams(requestInfoUrl, server.getClientId(), server.getClientSecret(), 
				token, getRedirectUri(server, this), code);
		// send request
		URLConnection connection = new URL(requestInfoUrl).openConnection();
		prepareConnection(connection);
		String sourceResponse = IOUtils.toString(connection.getInputStream(), "utf-8");
        // parse json result
        Map<String, String> result = new HashMap<String, String>();
        try {
			JSONObject parsedJson = new JSONObject(sourceResponse);
			result.put("login", parsedJson.getString(loginAttributeName));
			result.put("email", parsedJson.getString(emailAttributeName));
			if (parsedJson.has(firstname)) {
				result.put("firstname", parsedJson.getString(firstname));
			}
			if (parsedJson.has(lastname)) {
				result.put("lastname", parsedJson.getString(lastname));
			}
		} catch (JSONException e) {
			// try to parse response as canonical
			Map<String, String> parsedMap = parseCanonicalResponse(sourceResponse);
			result.put("login", parsedMap.get(loginAttributeName));
			result.put("email", parsedMap.get(emailAttributeName));
			if (parsedMap.containsKey(firstname)) {
				result.put("firstname", parsedMap.get(firstname));
			}
			if (parsedMap.containsKey(lastname)) {
				result.put("lastname", parsedMap.get(lastname));
			}
		}
		return result;
	}
	
	private void loginViaOAuth2(Map<String, String> params, long serverId) throws IOException, NoSuchAlgorithmException {
		UserDao userDao = getBean(UserDao.class);
		ConfigurationDao cfgDao = getBean(ConfigurationDao.class);
		String login = params.get("login");
		String email = params.get("email");
		String lastname = params.get("lastname");
		String firstname = params.get("firstname");
		if (firstname == null) {
			firstname = "";
		}
		if (lastname == null) {
			lastname = "";
		}
		if (!userDao.validLogin(login)) {
			log.error("Invalid login, please check parameters");
			return;
		}
		User u = userDao.getByLogin(login, Type.oauth, serverId);
		if (!userDao.checkEmail(email, Type.oauth, serverId, u == null ? null : u.getUser_id())) {
			log.error("Another user with the same email exists");
			return;
		}
		// generate random password
		byte[] rawPass = new byte[25];
		Random rnd = new Random();
		for (int i = 0; i < rawPass.length; ++i) {
			rawPass[i] = (byte) ('!' + rnd.nextInt(93));
		}
		String pass = new String(rawPass, "UTF-8");
		// check if the user already exists and register new one if it's needed
		if (u == null) {
			u = userDao.getNewUserInstance(null);
			u.setType(Type.oauth);
			u.getRights().remove(Right.Login);;
			u.setDomainId(serverId);
			u.getOrganisation_users().add(new Organisation_Users(getBean(OrganisationDao.class).get(cfgDao.getConfValue("default_domain_id", Long.class, "-1"))));
			u.setLogin(login);
			u.setShowContactDataToContacts(true);
			u.setLastname(lastname);
			u.setFirstname(firstname);
			u.getAdresses().setEmail(email);
		}
		u.setLastlogin(new Date());
		u = userDao.update(u, pass, -1);
		
		if (WebSession.get().signIn(login, pass, Type.oauth, serverId)) {
 			setResponsePage(Application.get().getHomePage());
		} else {
			log.error("Failed to login via OAuth2!");
		}
	}
		
	private static class AuthInfo {
			
		String accessToken;
		String refreshToken;
		String tokenType;
		long expiresIn;
			
		@Override
		public String toString() {
			return "AuthInfo [accessToken=" + accessToken + ", refreshToken="
					+ refreshToken + ", tokenType=" + tokenType
					+ ", expiresIn=" + expiresIn + "]";
		}
			
	}
	
}
