package page.tools.admin;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

import org.wikiwebserver.core.Privilege;
import org.wikiwebserver.core.WareHouse;
import org.wikiwebserver.handler.http.FormData;
import org.wikiwebserver.handler.http.HTTPException;
import org.wikiwebserver.handler.http.HTTPHandler;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;
import org.wikiwebserver.util.ValidationCorrection;
import org.wikiwebserver.util.ValidationError;
import org.wikiwebserver.util.ValidationWarning;
import org.wikiwebserver.util.Validator;

import page.tools.entity.Browser;
import page.tools.entity.User;
import page.tools.html.LiveFormPage;

import static org.wikiwebserver.html.HTMLHelper.*;

public class UserProfile extends LiveFormPage implements HTTPResponder {
    
    public void populate() {
    	
        User user = getSelectedUser();
        
        if (user != null) {
            putInputValue("userid", user.getId());
            putInputValue("e-mail", user.getEmail());
            putInputValue("password", null);
            putInputValue("newpassword", null);
            putInputValue("confirmpassword", null);
            putInputValue("fullname", (String) user.get("fullname"));
            putInputValue("showname", (String) user.get("showname"));
            putInputValue("website", (String) user.get("website"));
            putInputValue("profile", (String) user.get("profile"));
            putInputValue("country", (String) user.get("country"));
            putInputValue("privilege", (String) user.getPrivilege().getLabel());
        }  
    }    
       
    public void generate() {
        
        setTitle("User Profile - WikiWebServer.org");

        // Stores info about where to direct the user after registering
        String completeTarget = "";
        if (getFormData() != null) {
            String completeTargetPost = getFormData().getFirst("completetarget");
            if (completeTargetPost != null && completeTargetPost.length() > 0) {
                completeTarget = hiddenfield("completetarget", completeTargetPost);
            }
        }
        if (completeTarget.length() == 0) {
            String referer = getRequest().getHeaders().getFirst("Referer");  
            if (referer != null && referer.length() > 0) {
                completeTarget = hiddenfield("completetarget", referer);
            }
        }
        
        // Basic new user registration options
        String idField = "";
        String captchaField = liveCaptcha("captcha", "Human confirmation", 
                              "Copy the distorted text to prove you are human");
        String buttonLabel = "Register";
        String passwordHelp = "Please choose a password to secure the account";
        String newPasswordField = "";
        
        // When a user is logged in, changes page to editing functionality
        
        User u = getSelectedUser();
        if (u != null) {
            buttonLabel = "Update";
            idField = liveTextField("userid", "User ID", false, null);
            passwordHelp = null;
            newPasswordField = livePasswordField("newpassword", "New Password");
            captchaField = "";
        }
        
        append(h(1, "User profile"));
        
        append(form(h(2, "Required details") + 
               completeTarget +
               idField +
               liveTextField("e-mail", "Email", "This email address will be used to log in to WikiWebServer") +
               livePasswordField("password", "Password", passwordHelp) +
               newPasswordField +
               livePasswordField("confirmpassword", "Confirm Password") + 
               captchaField +
               liveSubmit(buttonLabel, "Clear") +
    
               h(2, "Optional details") +
    
               liveTextField("fullname", "Full name") +
               liveCheckbox("showname", "Show name", "Show my name instead of my email address") +
               liveTextField("website", "Website") +
               liveTextArea("profile", "Profile") +
               liveCheckbox("protectemail",  "Protect email", "Protect my email address from spam bots") + 
               liveDropdown("country", "Country", getCountryList()) +
    
               h(2, "User Privileges") +     
    
               liveRadioOptions("privilege", "User Privileges", getPrivilegeList(), null) +
               liveSubmit(buttonLabel, "Clear"))); 

    }    
    
    protected void complete(FormData validatedFormData) throws HTTPException {

        HTTPHandler conn = getHandler();
        User user = getSelectedUser(); 
        
        String action = validatedFormData.getFirst("action");
        if (action == null) return;
        
        if (action.equals("Register")) {
            String email = validatedFormData.getFirst("e-mail");
            String password = validatedFormData.getFirst("password");
            String captcha = validatedFormData.getFirst("captcha");
            user = User.addNewUser(email, password, captcha, conn);
            // Log the new user in
            user.startSession(password, conn);
        }
        
        if (user != null && (action.equals("Register") || action.equals("Update"))) {
            user.put("fullname", validatedFormData.getFirst("fullname"));
            user.put("showname", validatedFormData.getFirst("showname"));
            user.put("website", validatedFormData.getFirst("website"));
            user.put("profile", validatedFormData.getFirst("profile"));
            user.put("country", validatedFormData.getFirst("country"));
            
            user.setEmail(validatedFormData.getFirst("e-mail"), conn.getRequest());
            
            Privilege newPrivilege = Privilege.getPrivilegeFromLabel(validatedFormData.getFirst("privilege"));
            user.setPrivilege(newPrivilege, conn.getRequest());
            
            String password = validatedFormData.getFirst("password");
            String confirm = validatedFormData.getFirst("confirmpassword");
            if (confirm != null && confirm.length() > 0) {
                user.setPassword(password, confirm);
                putInputValue("password", null);
                putInputValue("newpassword", null);
                putInputValue("confirmpassword", null);
            }  
            

            String target = validatedFormData.getFirst("completetarget");
            if (target == null) {
                target = WareHouse.getUrlPathForClass(page.tools.stats.BrowserInfo.class) + 
                         "?userID=" + user.getId();
            }
            if (!target.startsWith("http")) {
                target = conn.getRequest().getHeaders().getFirst("Host") + target;
            }
            throw new HTTPException(302, "Registration complete", target);            
        }
        
    }
    
    public void validate(String name, String value) 
        throws ValidationCorrection, ValidationError, ValidationWarning {
        
        User user = getUser();
        User selectedUser = getSelectedUser();
        if (selectedUser != null) {
        	if (!selectedUser.equals(user)) {
	        	if (user != null && user.getPrivilege().isBelow(Privilege.MODERATOR)) {
	        		throw new ValidationError("You are not permitted to edit this user");
	        	}
	        	// This will check sessionAuth
	        	user.checkAuthorised(getRequest());
        	}
        }
        
        if ("e-mail".equals(name)) {
            if (value == null) throw new ValidationError("An email address is required");
            Validator.validateEmail(value);
            if (selectedUser == null || !selectedUser.getEmail().equals(value)) {
                if (User.isEmailRegistered(value)) {
                    throw new ValidationError("This email address is already registered");
                }
            }
        } 
        if ("password".equals(name)) {
        	if (!isSet(value) && selectedUser != null) {
	        	String email = getInputValue("e-mail");
	            if (!selectedUser.getEmail().equals(email)) {
	                throw new ValidationError("Password required to change email");
	            } 
	            
	        	String newpass = getInputValue("newpassword");
	            if (isSet(newpass)) {
	                throw new ValidationError("Previous or temporary password required to change password");
	            } 	            
        	}
        	
            if (selectedUser != null && isSet(value)) {
                if (!selectedUser.isCorrectPassword(value)) {
                    throw new ValidationError("Incorrect password");
                }
            }            
            else if (selectedUser == null || (isSet(value))) { 
                Validator.validatePassword(value); 
            }
        }
        if ("confirmpassword".equals(name)) {
            String pw = getInputValue("password");
            if (selectedUser != null) pw = getInputValue("newpassword");
            if (isSet(pw) && (!isSet(value) || !value.equals(pw))) {
                throw new ValidationError("Passwords must match");
            }
        } 
        if ("newpassword".equals(name)) {         
            if (selectedUser == null || (value != null && value.length() > 0)) { 
                Validator.validatePassword(value); 
            }
        }     
        if ("fullname".equals(name)) {
            if (isSet(getCurrentInputValue("showname")) && !isSet(value)) {
                throw new ValidationError("Please provide a full name to display");
            }
            if (!isSet(value)) return;
            String corrected = Validator.upperCaseFirstLetterOfWords(value);
            if (!corrected.equals(value)) {
                throw new ValidationCorrection("Corrected case", corrected);
            } 
            else if (value.split(" ").length == 1) {
                throw new ValidationError("Please provide first and last name");
            }
            else if (value.contains("<") || value.contains(">")) {
                throw new ValidationError("Invalid characters in name");
            }            
        }   
        if ("website".equals(name)) {
            if (!isSet(value)) return;
            if (value.length() > 0) {
                Validator.validateWebAddress(value);
            }
        }
        if ("profile".equals(name)) {
            if (!isSet(value)) return;
            if (value.contains("fuck")) {
                value = value.replaceAll("fuck", "");
                throw new ValidationCorrection("Bad word removed", value);
            }
        }        
        if ("privilege".equals(name)) {
            if (value == null) {
                throw new ValidationCorrection("Default new user level", Privilege.USER.getLabel());
            }
            
            if (value.equals(Privilege.BANNED.getLabel())) {
                throw new ValidationWarning("Warning: This will revoke access");
            }            
            if (value.equals(Privilege.GUEST.getLabel())) {
                throw new ValidationWarning("Warning: This will revoke user level access");
            }
                   
            if (user == null || user.getPrivilege().isBelow(Privilege.PREMIUM_USER)) {
                if (value.equals(Privilege.PREMIUM_USER.getLabel())) {
                    throw new ValidationError("Contribution required to increase privilege to premium user");
                }                
            }            
            if (user == null || user.getPrivilege().isBelow(Privilege.MODERATOR)) { 
                if (value.equals(Privilege.MODERATOR.getLabel())) {
                    throw new ValidationError("Please contact an administrator for moderator privilege");
                }               
            }
            if (user == null || user.getPrivilege().isBelow(Privilege.ADMIN)) {
                if (value.equals(Privilege.ADMIN.getLabel())) {
                    throw new ValidationError("Please contact a super administrator for admin privilege");
                }  
            }
            if (user == null || value.equals(Privilege.SUPER_ADMIN.getLabel())) {
                if (value.equals(Privilege.SUPER_ADMIN.getLabel())) {
                    throw new ValidationError("Super Administrator can not be assigned");
                }
            }             
        }  
        if ("protectemail".equals(name)) {
            if (!isSet(value)) {
                throw new ValidationCorrection("For your protection this option can not be disabled",
                                               "Protect my email address from spam bots");    
            }
        }         
        if ("captcha".equals(name)) {
            if (user == null) {
                validateCaptcha(value);
            }
        }
        if ("country".equals(name)) {
            Browser b = getBrowser();
            if (isSet(value) && value.trim().length() > 0) {
                String sourceCountry = (String) b.get("lastRequestCountry");
                if (sourceCountry == null || !sourceCountry.equalsIgnoreCase(value)) {
                    String msg = "Warning: Country does not match source IP block (" + sourceCountry + ")";
                    throw new ValidationWarning(msg);
                }
            }
        }        
    }

    
    private Collection<String> getCountryList() {
        
        List<String> countryList = new ArrayList<String>();
        countryList.add("");
        Locale[] locales = Locale.getAvailableLocales();
        
        for (int i = 0; i < locales.length; i++) {
            String countryName = locales[i].getDisplayCountry();
            if (countryName != null && countryName.length() > 0) {
                if (!countryList.contains(countryName)) {
                    countryList.add(countryName);
                }
            }
        }
        Collections.sort(countryList);
        
        return countryList;
    }
    
    private Collection<String> getPrivilegeList() {
        
        List<String> privilegeList = new ArrayList<String>();
        for (Privilege p : Privilege.values()) {
            privilegeList.add(p.getLabel());
        }        
        return privilegeList;
    }
    
    private User getSelectedUser() {
    	User user = getUser();
        if (getFormData() != null) {
        	String userId = getFormData().getFirst("userid");
        	if (userId != null) {
        		user = User.getUserById(userId);
        	}
        }    	
        return user;
    }
        
    public String getFormName() {
        return getClass().getName();
    }    
}
