package electrosphere.menu;

import java.util.List;

import electrosphere.auth.AuthenticationManager;
import electrosphere.engine.Globals;
import electrosphere.engine.loadingthreads.LoadingThread;
import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType;
import electrosphere.entity.scene.SceneGenerator;
import electrosphere.menu.mainmenu.MenuGeneratorsKeybind;
import electrosphere.menu.mainmenu.MenuGeneratorsTitleMenu;
import electrosphere.net.NetUtils;
import electrosphere.renderer.ui.elements.Button;
import electrosphere.renderer.ui.elements.Div;
import electrosphere.renderer.ui.elements.FormElement;
import electrosphere.renderer.ui.elements.Label;
import electrosphere.renderer.ui.elements.TextInput;
import electrosphere.renderer.ui.elementtypes.ClickableElement;
import electrosphere.renderer.ui.elementtypes.Element;
import electrosphere.renderer.ui.events.ClickEvent;
import electrosphere.server.saves.SaveUtils;

/**
 * Generator functions for creating menus
 */
public class MenuGenerators {

    //Used when we're displaying loading window to make main menu invisible
    public static Element createEmptyMainMenu(){
        Div rVal = Div.createDiv();
        return rVal;
    }
    
    public static Element createWorldSelectMenu(){
        FormElement rVal = new FormElement();
        // int screenTop = Globals.WINDOW_HEIGHT - 150;
        List<String> saveNames = SaveUtils.getSaves();
        int verticalPosition = 125;
        for(String saveName : saveNames){
            if(!saveName.startsWith(".")){

                //button (select save)
                Button selectButton = new Button();
                Label selectLabel = new Label(1.0f);
                selectLabel.setText(saveName.toUpperCase());
                selectButton.addChild(selectLabel);
                rVal.addChild(selectButton);
                selectButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
                    if(SaveUtils.saveHasWorldFile(saveName.toLowerCase())){
                        //need to log client in
                        Globals.clientUsername = "username";
                        Globals.clientPassword = AuthenticationManager.getHashedString("password");
                        LoadingThread clientThread = new LoadingThread(LoadingThreadType.CHARACTER_SERVER);
                        LoadingThread serverThread = new LoadingThread(LoadingThreadType.MAIN_GAME);
                        Globals.RUN_CLIENT = true;
                        Globals.RUN_SERVER = true;
                        Globals.threadManager.start(serverThread);
                        Globals.threadManager.start(clientThread);
                    } else {
                        SaveUtils.loadSave(saveName.toLowerCase(), false);
                        WindowUtils.replaceMainMenuContents(MenuGenerators.createSaveCreationMenu());
                    }
                    return false;
                }});

                verticalPosition = verticalPosition + 75;
            }
        }

        //button (create)
        Button createButton = new Button();
        Label createLabel = new Label(1.0f);
        createLabel.setText("Create World");
        createButton.addChild(createLabel);
        rVal.addChild(createButton);
        createButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
            WindowUtils.replaceMainMenuContents(MenuGenerators.createWorldCreationMenu());
            return false;
        }});

        return rVal;
    }
    
    public static Element createWorldCreationMenu(){
        FormElement rVal = new FormElement();
        int screenTop = 150;

        //TODO: add text input to name world
        //text entry (address)
        TextInput worldNameInput = new TextInput(100,screenTop + 125,1.0f);
        worldNameInput.setText("World name");
        rVal.addChild(worldNameInput);

        //button (create)
        Button createButton = new Button();
        Label createLabel = new Label(1.0f);
        createLabel.setText("Create");
        createButton.addChild(createLabel);
        rVal.addChild(createButton);
        createButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
            String saveName = worldNameInput.getText();
            //create save dir
            SaveUtils.createOrOverwriteSave(saveName, SceneGenerator.createProceduralSceneFile(saveName));
            WindowUtils.replaceMainMenuContents(MenuGenerators.createWorldSelectMenu());
            return false;
        }});

        return rVal;
    }
    
    public static Element createSaveCreationMenu(){
        FormElement rVal = new FormElement();

        //button (save)
        Button saveButton = new Button();
        Label saveLabel = new Label(1.0f);
        saveLabel.setText("Save");
        saveButton.addChild(saveLabel);
        rVal.addChild(saveButton);
        saveButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
            // SaveUtils.saveWorldData(Globals.currentSave.getName());
            WindowUtils.replaceMainMenuContents(MenuGenerators.createWorldSelectMenu());
            throw new UnsupportedOperationException("Need to update to use new save flow");
            // return false;
        }});

        //button (cancel)
        Button cancelButton = new Button();
        Label cancelLabel = new Label(1.0f);
        cancelLabel.setText("Cancel");
        cancelButton.addChild(cancelLabel);
        rVal.addChild(cancelButton);
        saveButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
            WindowUtils.replaceMainMenuContents(MenuGenerators.createWorldSelectMenu());
            return false;
        }});

        return rVal;
    }
    
    public static Element createCharacterCreationMenu(){
        FormElement rVal = new FormElement();
        
        //TODO: add text input to name world

        //button (create)
        Button createButton = new Button();
        Label createLabel = new Label(1.0f);
        createLabel.setText("Create World");
        createButton.addChild(createLabel);
        rVal.addChild(createButton);
        

        return rVal;
    }
    
    public static Element createFinalizeSaveCreationMenu(){
        FormElement rVal = new FormElement();

        //TODO: add text input to name world

        //button (create)
        Button createButton = new Button();
        Label createLabel = new Label(1.0f);
        createLabel.setText("Create World");
        createButton.addChild(createLabel);
        rVal.addChild(createButton);

        return rVal;
    }
    
    public static Element createMultiplayerMenu(){
        FormElement rVal = new FormElement();

        //button (host)
        Button hostButton = new Button();
        Label hostLabel = new Label(1.0f);
        hostLabel.setText("Host");
        hostButton.addChild(hostLabel);
        rVal.addChild(hostButton);
        hostButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
            LoadingThread clientThread = new LoadingThread(LoadingThreadType.CHARACTER_SERVER);
            LoadingThread serverThread = new LoadingThread(LoadingThreadType.MAIN_GAME);
            Globals.RUN_CLIENT = true;
            Globals.RUN_SERVER = true;
            Globals.threadManager.start(serverThread);
            Globals.threadManager.start(clientThread);
            return false;
        }});

        //button (join)
        Button joinButton = new Button();
        Label joinLabel = new Label(1.0f);
        joinLabel.setText("Join");
        joinButton.addChild(joinLabel);
        rVal.addChild(joinButton);
        joinButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
            WindowUtils.replaceMainMenuContents(MenuGenerators.createIPMenu());
            return false;
        }});
        

        //button (back)
        Button connectButton = new Button();
        Label connectLabel = new Label(1.0f);
        connectLabel.setText("Back");
        connectButton.addChild(connectLabel);
        rVal.addChild(connectButton);
        connectButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
            WindowUtils.replaceMainMenuContents(MenuGeneratorsTitleMenu.createTitleMenu());
            return false;
        }});

        return rVal;
    }
    
    public static Element createIPMenu(){
        FormElement rVal = new FormElement();
        int screenTop = 150;
        
        //label (address)
        Label addressLabel = new Label(1.0f);
        addressLabel.setText("IP Address");
        rVal.addChild(addressLabel);

        //text entry (address)
        TextInput addressInput = new TextInput(100,screenTop + 125,1.0f);
        if(Globals.netConfig != null && Globals.netConfig.getAddress() != null){
            addressInput.setText(Globals.netConfig.getAddress());
        } else {
            addressInput.setText(NetUtils.getAddress());
        }
        rVal.addChild(addressInput);

        //label (port)
        Label portLabel = new Label(1.0f);
        portLabel.setText("Port");
        rVal.addChild(portLabel);

        //text entry (port)
        TextInput portInput = new TextInput(100,screenTop + 275,1.0f);
        if(Globals.netConfig != null && Globals.netConfig.getPort() != null){
            portInput.setText(Globals.netConfig.getPort());
        } else {
            portInput.setText(NetUtils.getPort() + "");
        }
        rVal.addChild(portInput);

        //label (address)
        Label usernameLabel = new Label(1.0f);
        usernameLabel.setText("Username");
        rVal.addChild(usernameLabel);

        //text entry (address)
        TextInput usernameInput = new TextInput(100,screenTop + 425,1.0f);
        if(Globals.netConfig != null && Globals.netConfig.getUsername() != null){
            usernameInput.setText(Globals.netConfig.getUsername());
        } else {
            usernameInput.setText("");
        }
        rVal.addChild(usernameInput);

        //label (port)
        Label passwordLabel = new Label(1.0f);
        passwordLabel.setText("Password");
        rVal.addChild(passwordLabel);

        //text entry (port)
        TextInput passwordInput = new TextInput(100,screenTop + 575,1.0f);
        if(Globals.netConfig != null && Globals.netConfig.getUsername() != null){
            passwordInput.setText(Globals.netConfig.getPassword());
        } else {
            passwordInput.setText("");
        }
        rVal.addChild(passwordInput);

        //button (connect)
        Button connectButton = new Button();
        Label connectLabel = new Label(1.0f);
        connectLabel.setText("Connect");
        connectButton.addChild(connectLabel);
        rVal.addChild(connectButton);
        connectButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
            NetUtils.setAddress(addressInput.getText());
            NetUtils.setPort(Integer.parseInt(portInput.getText()));
            Globals.clientUsername = usernameInput.getText();
            Globals.clientPassword = AuthenticationManager.getHashedString(passwordInput.getText());
            LoadingThread clientThread = new LoadingThread(LoadingThreadType.CHARACTER_SERVER);
            Globals.RUN_CLIENT = true;
            Globals.RUN_SERVER = false;
            Globals.threadManager.start(clientThread);
            return false;
        }});

        //button (back)
        Button backButton = new Button();
        Label backLabel = new Label(1.0f);
        backLabel.setText("Back");
        backButton.addChild(backLabel);
        rVal.addChild(backButton);
        backButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
            WindowUtils.replaceMainMenuContents(MenuGenerators.createMultiplayerMenu());
            return false;
        }});

        return rVal;
    }
    
    public static Element createOptionsMainMenu(){
        FormElement rVal = new FormElement();
        
        //label (options)
        Label optionsLabel = new Label(1.0f);
        optionsLabel.setText("Options");
        rVal.addChild(optionsLabel);

        //button (back)
        Button backButton = new Button();
        Label backLabel = new Label(1.0f);
        backLabel.setText("Back");
        backButton.addChild(backLabel);
        rVal.addChild(backButton);
        backButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
            WindowUtils.replaceMainMenuContents(MenuGeneratorsTitleMenu.createTitleMenu());
            return false;
        }});

        //button to open rebind controls window
        Button rebindControlsButton = Button.createButton("Controls", () -> {
            WindowUtils.replaceMainMenuContents(MenuGeneratorsKeybind.createControlsRebindMenu());
        });
        rVal.addChild(rebindControlsButton);

        return rVal;
    }

    
    
}
