package org.keycloak.testsuite.console.page.clients.mappers;

import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
import org.keycloak.testsuite.page.Form;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.ui.Select;


/**
 * @author Vaclav Muzikar <vmuzikar@redhat.com>
 *
 * TODO: SAML
 */
public class CreateClientMappersForm extends Form {

    // Mappers types
    public static final String HARDCODED_ROLE = "Hardcoded Role";
    public static final String HARDCODED_CLAIM = "Hardcoded claim";
    public static final String USER_SESSION_NOTE = "User Session Note";
    public static final String ROLE_NAME_MAPPER = "Role Name Mapper";
    public static final String USER_ADDRESS = "User Address";
    public static final String USERS_FULL_NAME = "User's full name";
    public static final String USER_ATTRIBUTE = "User Attribute";
    public static final String USER_PROPERTY = "User Property";
    public static final String GROUP_MEMBERSHIP = "Group Membership";

    // Role types
    public static final String REALM_ROLE = "realm";
    public static final String CLIENT_ROLE = "client";
    
    @FindBy(id = "name")
    private WebElement nameElement;

    @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='consentRequired']]")
    private OnOffSwitch consentRequiredSwitch;

    @FindBy(id = "consentText")
    private WebElement consentTextElement;

    @FindBy(id = "mapperTypeCreate")
    private Select mapperTypeSelect;

    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Property']//following-sibling::node()//input[@type='text']")
    private WebElement propertyInput;

    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='User Attribute']//following-sibling::node()//input[@type='text']")
    private WebElement userAttributeInput;

    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='User Session Note']//following-sibling::node()//input[@type='text']")
    private WebElement userSessionNoteInput;

    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Multivalued']//following-sibling::node()//div[@class='onoffswitch']")
    private OnOffSwitch multivaluedInput;

    @FindBy(xpath = ".//button[text() = 'Select Role']/../..//input")
    private WebElement roleInput;

    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='New Role Name']//following-sibling::node()//input[@type='text']")
    private WebElement newRoleInput;

    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Token Claim Name']//following-sibling::node()//input[@type='text']")
    private WebElement tokenClaimNameInput;

    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Claim value']//following-sibling::node()//input[@type='text']")
    private WebElement tokenClaimValueInput;

    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Claim JSON Type']//following-sibling::node()//select")
    private Select claimJSONTypeInput;

    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Add to ID token']//following-sibling::node()//div[@class='onoffswitch']")
    private OnOffSwitch addToIDTokenInput;

    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Add to access token']//following-sibling::node()//div[@class='onoffswitch']")
    private OnOffSwitch addToAccessTokenInput;
    
    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Full group path']//following-sibling::node()//div[@class='onoffswitch']")
    private OnOffSwitch fullGroupPath;

    @FindBy(xpath = ".//button[text() = 'Select Role']")
    private WebElement selectRoleButton;
            
    @FindBy(xpath = "//div[@class='modal-dialog']")
    private RoleSelectorModalDialog roleSelectorModalDialog;

    public class RoleSelectorModalDialog {
        @FindBy(id = "available")
        private Select realmAvailable;
        @FindBy(xpath = ".//button[@tooltip='Select realm role']")
        private WebElement selectRealmRoleButton;
        
        @FindBy(id = "available-client")
        private Select clientAvailable;
        @FindBy(id = "clients")
        private Select clientSelect;
        @FindBy(xpath = ".//button[@tooltip='Select client role']")
        private WebElement selectClientRoleButton;
        @FindBy(xpath = ".//button[@class='close']")
        private WebElement closeButton;
        
        public void closeRoleSelectorModalDialog() {
            closeButton.click();
        }
        
        public void selectRealmRole(String roleName) {
            if (roleName != null) {
                realmAvailable.selectByVisibleText(roleName);
            }
            selectRealmRoleButton.click();
        }
        
        public void selectClientRole(String clientName, String roleName) {
            if (roleName != null || clientName != null) {
                clientSelect.selectByVisibleText(clientName);
                clientAvailable.selectByVisibleText(roleName);
            }
            selectClientRoleButton.click();
        }
    }
    
    public void selectRole(String roleType, String roleName, String clientName) {
        selectRoleButton.click();
        switch (roleType) {
            case REALM_ROLE:
                roleSelectorModalDialog.selectRealmRole(roleName);
                break;
            case CLIENT_ROLE:
                roleSelectorModalDialog.selectClientRole(clientName, roleName);
                break;
            default:
                throw new IllegalArgumentException("No such role type, use \"" + 
                        REALM_ROLE + "\" or \"" + CLIENT_ROLE + "\"");
        }
    }
    
    public void closeRoleSelectorModalDialog() {
        roleSelectorModalDialog.closeRoleSelectorModalDialog();
    }
    
    public void setName(String value) {
        setInputValue(nameElement, value);
    }
    
    public boolean isConsentRequired() {
        return consentRequiredSwitch.isOn();
    }

    public void setConsentRequired(boolean consentRequired) {
        consentRequiredSwitch.setOn(consentRequired);
    }

    public String getConsentText() {
        return getInputValue(consentTextElement);
    }

    public void setConsentText(String consentText) {
        setInputValue(consentTextElement, consentText);
    }

    public void setMapperType(String type) {
        mapperTypeSelect.selectByVisibleText(type);
    }
    
    public String getProperty() {
        return getInputValue(propertyInput);
    }
    
    public void setProperty(String value) {
        setInputValue(propertyInput, value);
    }

    public String getUserAttribute() {
        return getInputValue(userAttributeInput);
    }

    public void setUserAttribute(String value) {
        setInputValue(userAttributeInput, value);
    }

    public String getUserSessionNote() {
        return getInputValue(userSessionNoteInput);
    }

    public void setUserSessionNote(String value) {
        setInputValue(userSessionNoteInput, value);
    }

    public boolean isMultivalued() {
        return multivaluedInput.isOn();
    }

    public void setMultivalued(boolean value) {
        multivaluedInput.setOn(value);
    }

    public String getRole() {
        return getInputValue(roleInput);
    }

    public void setRole(String value) {
        setInputValue(roleInput, value);
    }

    public String getNewRole() {
        return getInputValue(newRoleInput);
    }

    public void setNewRole(String value) {
        setInputValue(newRoleInput, value);
    }

    public String getTokenClaimName() {
        return getInputValue(tokenClaimNameInput);
    }

    public void setTokenClaimName(String value) {
        setInputValue(tokenClaimNameInput, value);
    }

    public String getTokenClaimValue() {
        return getInputValue(tokenClaimValueInput);
    }

    public void setTokenClaimValue(String value) {
        setInputValue(tokenClaimValueInput, value);
    }

    public String getClaimJSONType() {
        return claimJSONTypeInput.getFirstSelectedOption().getText();
    }

    public void setClaimJSONType(String value) {
        claimJSONTypeInput.selectByVisibleText(value);
    }

    public boolean isAddToIDToken() {
        return addToIDTokenInput.isOn();
    }

    public void setAddToIDToken(boolean value) {
        addToIDTokenInput.setOn(value);
    }

    public boolean isAddToAccessToken() {
        return addToAccessTokenInput.isOn();
    }

    public void setAddToAccessToken(boolean value) {
        addToAccessTokenInput.setOn(value);
    }
    
    public boolean isFullGroupPath() {
        return fullGroupPath.isOn();
    }
    
    public void setFullGroupPath(boolean value) {
        fullGroupPath.setOn(value);
    }

}
