/*
 * 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.HashMap;
import java.util.Map;

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.IUserManager;
import org.apache.openmeetings.db.entity.server.OAuthServer;
import org.apache.openmeetings.db.entity.user.User;
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;
	private KickMessageDialog m;
	
	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);
		m = new KickMessageDialog("kick");
		add(d.setVisible(!WebSession.get().isKickedByAdmin()), 
				r.setVisible(allowRegister()), f, m.setVisible(WebSession.get().isKickedByAdmin()));
	}
	
	public SignInPage() {
		this(new PageParameters());
	}
	
	@Override
	public void renderHead(IHeaderResponse response) {
		super.renderHead(response);
		response.render(OnDomReadyHeaderItem.forScript(m.getOnClickJavaScript()));
		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 = "";
		if (server.getId() != null) {
			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 {
		User u = getBean(IUserManager.class).loginOAuth(params, serverId);
		
		if (u != null && WebSession.get().signIn(u)) {
 			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 + "]";
		}
			
	}
	
}
