<commit_before>package model;

import java.util.Observable;
import java.util.Optional;

import model.exceptions.CampaignExistsException;
import model.exceptions.CampaignNotFoundException;
import model.exceptions.LevelExistsException;
import model.exceptions.LevelNotFoundException;
import model.exceptions.SaveLoadException;
import model.sprite.SpriteImageContainer;
import model.sprite.SpriteImageGenerator;
import model.state.CampaignState;
import model.state.DescribableState;
import model.state.GameState;
import model.state.LevelState;
import model.state.gameelement.DrawableGameElementState;
import model.state.gameelement.GameElementState;
import model.state.gameelement.SelectableGameElementState;
import model.state.gameelement.StateTags;
import util.GameSaveLoadMediator;
import util.multilanguage.MultiLanguageUtility;
import view.dialog.DialogBoxUtility;
import view.editor.wizards.WizardData;
import view.editor.wizards.WizardDataType;

/**
 * Main class for the model of the game
 * 
 * @author <NAME>, <NAME>, <NAME>
 *
 */
public class MainModel extends Observable {

    private static final String LOAD_GAME_ERROR_KEY = "LoadGameError";

    private GameState myGameState;
    private GameElementState myEditorSelectedElement;
    private GameSaveLoadMediator mySaveLoadMediator;
    private SpriteImageGenerator mySpriteImageGenerator;
    private ModifiedContainer myModifiedContainer;

    public MainModel () {
        try {
            mySaveLoadMediator = new GameSaveLoadMediator();
            mySpriteImageGenerator = new SpriteImageGenerator();
            myModifiedContainer = new ModifiedContainer();
        } catch (SaveLoadException e) {
            System.out.println(mySpriteImageGenerator == null);
            e.printStackTrace();
        }
    }

    public void newGame (String gameName) {
        // TODO CLEAN THIS UP
        myGameState = new GameState(gameName);
    }

    /**
     * Sets the game of the Model.
     * 
     * @param game
     * @throws Exception
     */
    public void loadGame (String game) throws Exception {

        try {
            // TODO: insert Save Load code here and instantiate myGameState
            myGameState = mySaveLoadMediator.loadGame(game);
        } catch (SaveLoadException e) {
            // TODO Get rid of stack trace printing
            DialogBoxUtility.createMessageDialog(MultiLanguageUtility.getInstance()
                    .getStringProperty(LOAD_GAME_ERROR_KEY).getValue());
        }
        updateObservers();
    }

    public void saveGame () throws RuntimeException {
        saveGame(myGameState);
    }

    public void saveGame (GameState game) {
        try {
            // TODO: Save location
            String location = mySaveLoadMediator.saveGame(game, game.getName());

        } catch (SaveLoadException e) {

            // TODO: eliminate stack trace printing
            e.printStackTrace();
            // throw new RuntimeException(e);
        }
    }

    public void updateDescribableState (String[] selection, String name, String description)
            throws CampaignNotFoundException, LevelNotFoundException {
        DescribableState state = getDescribableState(selection);
        state.updateName(name);
        state.updateDescription(description);
        updateObservers();
    }

    public DescribableState getDescribableState (String[] selection)
            throws CampaignNotFoundException, LevelNotFoundException {
        if (selection[2].isEmpty()) {
            if (selection[1].isEmpty()) {
                return myGameState;
            } else {
                return myGameState.getCampaign(selection[1]);
            }
        } else {
            return myGameState.getCampaign(selection[1]).getLevel(selection[2]);
        }
    }

    public GameState getCurrentGame () {
        return myGameState;
    }

    public LevelState getLevel (String campaignName, String levelName)
            throws LevelNotFoundException, CampaignNotFoundException {
        return getCampaign(campaignName).getLevel(levelName);
    }

    public CampaignState getCampaign (String campaignName) throws CampaignNotFoundException {
        return myGameState.getCampaign(campaignName);
    }

    /**
     * called by editor when user selects new element from accordion pane
     * 
     * @param element
     */
    public void setEditorSelected (String elementName) {
        updateObservers();
    }

    /**
     * called by engine when registers click and needs what the editor has
     * selected to place on the map
     */
    public GameElementState getEditorSelected () {
        return myEditorSelectedElement;
    }

    /**
     * called by editor when creating a new campaign
     * 
     * @param campaignName
     * @throws CampaignExistsException
     */
    public void createCampaign (String campaignName) throws CampaignExistsException {
        CampaignState newCampaignState = new CampaignState(campaignName.trim());
        myGameState.addCampaign(newCampaignState);
        updateObservers();
    }

    /**
     * called by editor when creating a new level under a certain campaign
     * 
     * @param campaignName
     * @param levelName
     * @throws LevelExistsException
     */
    public void createLevel (String levelName, String campaignName, Number width, Number height)
            throws LevelExistsException, CampaignNotFoundException, Exception {
        CampaignState campaignState = myGameState.getCampaign(campaignName.trim());
        LevelState newLevelState = new LevelState(levelName.trim());
        if (width.doubleValue() > 0 && height.doubleValue() > 0) {
            newLevelState.attributes.setNumericalAttribute(StateTags.LEVEL_WIDTH, width);
            newLevelState.attributes.setNumericalAttribute(StateTags.LEVEL_HEIGHT, height);
        } else {
            throw new Exception("invalid size of level");
        }
        campaignState.addLevel(newLevelState);
        updateObservers();
    }

    /**
     * called by editor when creating a new game element
     * 
     * @param data
     */
    public void createGameElementState (WizardData data) {
        GameElementState gameElement = GameElementStateFactory.createGameElementState(data);
        myGameState.getGameUniverse().addGameElementState(gameElement);
        updateObservers();
    }

    /**
     * called by editor when creating a new game element
     * 
     * @param data
     */
    public void createDrawableGameElementState (WizardData data) {
        try {
            String actualSaveLocation = mySaveLoadMediator.saveImage(data);
            data.addDataPair(WizardDataType.IMAGE, actualSaveLocation);
            DrawableGameElementState gameElement = GameElementStateFactory
                    .createDrawableGameElementState(data);
            myGameState.getGameUniverse().addDrawableGameElementState(gameElement);
            updateObservers();
        } catch (SaveLoadException e) {
            // TODO remove
            e.printStackTrace();
        }
    }

    /**
     * called by editor when creating a new game element
     * 
     * @param data
     */
    public void createSelectableGameElementState (WizardData data) {
        try {
            String actualSaveLocation = mySaveLoadMediator.saveImage(data);
            data.addDataPair(WizardDataType.IMAGE, actualSaveLocation);

            SelectableGameElementState gameElement = GameElementStateFactory
                    .createSelectableGameElementState(data);
            myGameState.getGameUniverse().addSelectableGameElementState(gameElement);
            updateObservers();
        } catch (SaveLoadException e) {
            // TODO remove
            e.printStackTrace();
        }
    }

    public void removeDrawableGameElement (String elementName) {
        Optional<DrawableGameElementState> option = getGameUniverse()
                .getDrawableGameElementStates().stream().filter( (state) -> {
                    return state.getName().equals(elementName);
                }).findFirst();
        if (option.isPresent()) {
            getGameUniverse().removeDrawableGameElementState(option.get());
        }
    }

    public void removeSelectableGameElement (String elementName) {
        Optional<SelectableGameElementState> option = getGameUniverse()
                .getSelectableGameElementStates().stream().filter( (state) -> {
                    return state.getName().equals(elementName);
                }).findFirst();
        if (option.isPresent()) {
            getGameUniverse().removeSelectableGameElementState(option.get());
        }
    }

    public void createGoal (LevelState levelState, WizardData data) {
        GameElementState goal = GameElementStateFactory.createGoal(data);
        levelState.addGoal(goal);
        myModifiedContainer.getRecentlyAddedGoals().add(goal);
        updateObservers();
    }

    public void removeGoal (LevelState levelState, int index) {
        GameElementState goal = levelState.getGoals().get(index);
        levelState.getGoals().remove(goal);
        myModifiedContainer.getRecentlyDeletedGoals().add(goal);
        updateObservers();
    }

    public void addUnitToLevel (LevelState levelState, String elementName, Double xValue,
            Double yValue) throws Exception {
        if (areCoordinatesValid(levelState, xValue, yValue)) {
            SelectableGameElementState unit = getGameUniverse().getSelectableGameElementState(
                    elementName);
            unit.attributes.setNumericalAttribute(StateTags.X_POSITION, xValue);
            unit.attributes.setNumericalAttribute(StateTags.Y_POSITION, yValue);
            myModifiedContainer.getRecentlyAddedUnits().add(unit);
            levelState.addUnit(unit);
        } else {
            throw new Exception("location not within level grid bounds");
        }

    }

    public void setTerrain (LevelState levelState, String terrainName) {
        int width = levelState.attributes.getNumericalAttribute(StateTags.LEVEL_WIDTH).intValue();
        int height = levelState.attributes.getNumericalAttribute(StateTags.LEVEL_HEIGHT).intValue();
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                DrawableGameElementState terrain = getGameUniverse().getDrawableGameElementState(
                        terrainName);
                terrain.attributes.setNumericalAttribute(StateTags.X_POSITION, i);
                terrain.attributes.setNumericalAttribute(StateTags.Y_POSITION, j);
                myModifiedContainer.getRecentlyAddedTerrain().add(terrain);
                levelState.addTerrain(terrain);
            }
        }
    }

    public void addTerrainToLevel (LevelState levelState, String elementName, Double xValue,
            Double yValue) throws Exception {
        if (areCoordinatesValid(levelState, xValue, yValue)) {
            DrawableGameElementState terrain = getGameUniverse().getDrawableGameElementState(
                    elementName);
            terrain.attributes.setNumericalAttribute(StateTags.X_POSITION, xValue);
            terrain.attributes.setNumericalAttribute(StateTags.Y_POSITION, yValue);
            myModifiedContainer.getRecentlyAddedTerrain().add(terrain);
            levelState.addTerrain(terrain);
        } else {
            throw new Exception("location not within level grid bounds");
        }
    }

    private boolean areCoordinatesValid (LevelState levelState, Double x, Double y) {
        Number width = levelState.attributes.getNumericalAttribute(StateTags.LEVEL_WIDTH);
        Number height = levelState.attributes.getNumericalAttribute(StateTags.LEVEL_HEIGHT);
        return (x >= 0 && width.doubleValue() > x && y >= 0 && height.doubleValue() > y);
    }

    private void updateObservers () {
        setChanged();
        notifyObservers();
        clearChanged();
    }

    /**
     * gets the game universe (list of all elements that could be used in the
     * currently selected game
     * 
     * @return
     */
    public GameUniverse getGameUniverse () {
        return myGameState.getGameUniverse();
    }

    public ModifiedContainer getModifiedContainer () {
        return myModifiedContainer;
    }

    /**
     * 
     * @param imageTag
     * @return
     * @throws Exception
     */
    public SpriteImageContainer fetchImageContainer (String imageTag) {
        return mySpriteImageGenerator.fetchImageContainer(imageTag);
    }

}<commit_msg>Main model update<commit_after>package model;

import java.util.Observable;
import java.util.Optional;

import model.exceptions.CampaignExistsException;
import model.exceptions.CampaignNotFoundException;
import model.exceptions.LevelExistsException;
import model.exceptions.LevelNotFoundException;
import model.exceptions.SaveLoadException;
import model.sprite.SpriteImageContainer;
import model.sprite.SpriteImageGenerator;
import model.state.CampaignState;
import model.state.DescribableState;
import model.state.GameState;
import model.state.LevelState;
import model.state.gameelement.DrawableGameElementState;
import model.state.gameelement.GameElementState;
import model.state.gameelement.SelectableGameElementState;
import model.state.gameelement.StateTags;
import util.GameSaveLoadMediator;
import util.multilanguage.LanguagePropertyNotFoundException;
import util.multilanguage.MultiLanguageUtility;
import view.dialog.DialogBoxUtility;
import view.editor.wizards.WizardData;
import view.editor.wizards.WizardDataType;

/**
 * Main class for the model of the game
 * 
 * @author <NAME>, <NAME>, <NAME>
 *
 */
public class MainModel extends Observable {

    private static final String LOAD_GAME_ERROR_KEY = "LoadGameError";

    private GameState myGameState;
    private GameElementState myEditorSelectedElement;
    private GameSaveLoadMediator mySaveLoadMediator;
    private SpriteImageGenerator mySpriteImageGenerator;
    private ModifiedContainer myModifiedContainer;

    public MainModel () {
        try {
            mySaveLoadMediator = new GameSaveLoadMediator();
            mySpriteImageGenerator = new SpriteImageGenerator();
            myModifiedContainer = new ModifiedContainer();
        } catch (SaveLoadException e) {
            System.out.println(mySpriteImageGenerator == null);
            e.printStackTrace();
        }
    }

    public void newGame (String gameName) {
        // TODO CLEAN THIS UP
        myGameState = new GameState(gameName);
    }

    /**
     * Sets the game of the Model.
     * 
     * @param game
     * @throws LanguagePropertyNotFoundException
     */
    public void loadGame (String game) throws LanguagePropertyNotFoundException {
        // TODO: Move the dialog box utility message dialog to a View class as
        // opposed to in model.
        try {
            // TODO: insert Save Load code here and instantiate myGameState
            myGameState = mySaveLoadMediator.loadGame(game);
        } catch (SaveLoadException e) {
            // TODO Get rid of stack trace printing
            DialogBoxUtility.createMessageDialog(MultiLanguageUtility.getInstance()
                    .getStringProperty(LOAD_GAME_ERROR_KEY).getValue());
        }
        updateObservers();
    }

    public void saveGame () throws RuntimeException {
        saveGame(myGameState);
    }

    public void saveGame (GameState game) {
        try {
            // TODO: Save location
            String location = mySaveLoadMediator.saveGame(game, game.getName());

        } catch (SaveLoadException e) {

            // TODO: eliminate stack trace printing
            e.printStackTrace();
            // throw new RuntimeException(e);
        }
    }

    public void updateDescribableState (String[] selection, String name, String description)
            throws CampaignNotFoundException, LevelNotFoundException {
        DescribableState state = getDescribableState(selection);
        state.updateName(name);
        state.updateDescription(description);
        updateObservers();
    }

    public DescribableState getDescribableState (String[] selection)
            throws CampaignNotFoundException, LevelNotFoundException {
        if (selection[2].isEmpty()) {
            if (selection[1].isEmpty()) {
                return myGameState;
            } else {
                return myGameState.getCampaign(selection[1]);
            }
        } else {
            return myGameState.getCampaign(selection[1]).getLevel(selection[2]);
        }
    }

    public GameState getCurrentGame () {
        return myGameState;
    }

    public LevelState getLevel (String campaignName, String levelName)
            throws LevelNotFoundException, CampaignNotFoundException {
        return getCampaign(campaignName).getLevel(levelName);
    }

    public CampaignState getCampaign (String campaignName) throws CampaignNotFoundException {
        return myGameState.getCampaign(campaignName);
    }

    /**
     * called by editor when user selects new element from accordion pane
     * 
     * @param element
     */
    public void setEditorSelected (String elementName) {
        updateObservers();
    }

    /**
     * called by engine when registers click and needs what the editor has
     * selected to place on the map
     */
    public GameElementState getEditorSelected () {
        return myEditorSelectedElement;
    }

    /**
     * called by editor when creating a new campaign
     * 
     * @param campaignName
     * @throws CampaignExistsException
     */
    public void createCampaign (String campaignName) throws CampaignExistsException {
        CampaignState newCampaignState = new CampaignState(campaignName.trim());
        myGameState.addCampaign(newCampaignState);
        updateObservers();
    }

    /**
     * called by editor when creating a new level under a certain campaign
     * 
     * @param campaignName
     * @param levelName
     * @throws LevelExistsException
     */
    public void createLevel (String levelName, String campaignName, Number width, Number height)
            throws LevelExistsException, CampaignNotFoundException, Exception {
        CampaignState campaignState = myGameState.getCampaign(campaignName.trim());
        LevelState newLevelState = new LevelState(levelName.trim());
        if (width.doubleValue() > 0 && height.doubleValue() > 0) {
            newLevelState.attributes.setNumericalAttribute(StateTags.LEVEL_WIDTH, width);
            newLevelState.attributes.setNumericalAttribute(StateTags.LEVEL_HEIGHT, height);
        } else {
            throw new Exception("invalid size of level");
        }
        campaignState.addLevel(newLevelState);
        updateObservers();
    }

    /**
     * called by editor when creating a new game element
     * 
     * @param data
     */
    public void createGameElementState (WizardData data) {
        GameElementState gameElement = GameElementStateFactory.createGameElementState(data);
        myGameState.getGameUniverse().addGameElementState(gameElement);
        updateObservers();
    }

    /**
     * called by editor when creating a new game element
     * 
     * @param data
     */
    public void createDrawableGameElementState (WizardData data) {
        try {
            String actualSaveLocation = mySaveLoadMediator.saveImage(data);
            data.addDataPair(WizardDataType.IMAGE, actualSaveLocation);
            DrawableGameElementState gameElement = GameElementStateFactory
                    .createDrawableGameElementState(data);
            myGameState.getGameUniverse().addDrawableGameElementState(gameElement);
            updateObservers();
        } catch (SaveLoadException e) {
            // TODO remove
            e.printStackTrace();
        }
    }

    /**
     * called by editor when creating a new game element
     * 
     * @param data
     */
    public void createSelectableGameElementState (WizardData data) {
        try {
            String actualSaveLocation = mySaveLoadMediator.saveImage(data);
            data.addDataPair(WizardDataType.IMAGE, actualSaveLocation);

            SelectableGameElementState gameElement = GameElementStateFactory
                    .createSelectableGameElementState(data);
            myGameState.getGameUniverse().addSelectableGameElementState(gameElement);
            updateObservers();
        } catch (SaveLoadException e) {
            // TODO remove
            e.printStackTrace();
        }
    }

    public void removeDrawableGameElement (String elementName) {
        Optional<DrawableGameElementState> option = getGameUniverse()
                .getDrawableGameElementStates().stream().filter( (state) -> {
                    return state.getName().equals(elementName);
                }).findFirst();
        if (option.isPresent()) {
            getGameUniverse().removeDrawableGameElementState(option.get());
        }
    }

    public void removeSelectableGameElement (String elementName) {
        Optional<SelectableGameElementState> option = getGameUniverse()
                .getSelectableGameElementStates().stream().filter( (state) -> {
                    return state.getName().equals(elementName);
                }).findFirst();
        if (option.isPresent()) {
            getGameUniverse().removeSelectableGameElementState(option.get());
        }
    }

    public void createGoal (LevelState levelState, WizardData data) {
        GameElementState goal = GameElementStateFactory.createGoal(data);
        levelState.addGoal(goal);
        myModifiedContainer.getRecentlyAddedGoals().add(goal);
        updateObservers();
    }

    public void removeGoal (LevelState levelState, int index) {
        GameElementState goal = levelState.getGoals().get(index);
        levelState.getGoals().remove(goal);
        myModifiedContainer.getRecentlyDeletedGoals().add(goal);
        updateObservers();
    }

    public void addUnitToLevel (LevelState levelState, String elementName, Double xValue,
            Double yValue) throws Exception {
        if (areCoordinatesValid(levelState, xValue, yValue)) {
            SelectableGameElementState unit = getGameUniverse().getSelectableGameElementState(
                    elementName);
            unit.attributes.setNumericalAttribute(StateTags.X_POSITION, xValue);
            unit.attributes.setNumericalAttribute(StateTags.Y_POSITION, yValue);
            myModifiedContainer.getRecentlyAddedUnits().add(unit);
            levelState.addUnit(unit);
        } else {
            throw new Exception("location not within level grid bounds");
        }

    }

    public void setTerrain (LevelState levelState, String terrainName) {
        int width = levelState.attributes.getNumericalAttribute(StateTags.LEVEL_WIDTH).intValue();
        int height = levelState.attributes.getNumericalAttribute(StateTags.LEVEL_HEIGHT).intValue();
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                DrawableGameElementState terrain = getGameUniverse().getDrawableGameElementState(
                        terrainName);
                terrain.attributes.setNumericalAttribute(StateTags.X_POSITION, i);
                terrain.attributes.setNumericalAttribute(StateTags.Y_POSITION, j);
                myModifiedContainer.getRecentlyAddedTerrain().add(terrain);
                levelState.addTerrain(terrain);
            }
        }
    }

    public void addTerrainToLevel (LevelState levelState, String elementName, Double xValue,
            Double yValue) throws Exception {
        if (areCoordinatesValid(levelState, xValue, yValue)) {
            DrawableGameElementState terrain = getGameUniverse().getDrawableGameElementState(
                    elementName);
            terrain.attributes.setNumericalAttribute(StateTags.X_POSITION, xValue);
            terrain.attributes.setNumericalAttribute(StateTags.Y_POSITION, yValue);
            myModifiedContainer.getRecentlyAddedTerrain().add(terrain);
            levelState.addTerrain(terrain);
        } else {
            throw new Exception("location not within level grid bounds");
        }
    }

    private boolean areCoordinatesValid (LevelState levelState, Double x, Double y) {
        Number width = levelState.attributes.getNumericalAttribute(StateTags.LEVEL_WIDTH);
        Number height = levelState.attributes.getNumericalAttribute(StateTags.LEVEL_HEIGHT);
        return (x >= 0 && width.doubleValue() > x && y >= 0 && height.doubleValue() > y);
    }

    private void updateObservers () {
        setChanged();
        notifyObservers();
        clearChanged();
    }

    /**
     * gets the game universe (list of all elements that could be used in the
     * currently selected game
     * 
     * @return
     */
    public GameUniverse getGameUniverse () {
        return myGameState.getGameUniverse();
    }

    public ModifiedContainer getModifiedContainer () {
        return myModifiedContainer;
    }

    /**
     * 
     * @param imageTag
     * @return
     * @throws Exception
     */
    public SpriteImageContainer fetchImageContainer (String imageTag) {
        return mySpriteImageGenerator.fetchImageContainer(imageTag);
    }

}
{'fraction_non_alphanumeric': 0.0826095578028951, 'fraction_numerical': 0.0008724965298433472, 'mean_word_length': 2.722468260997933, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1970425', 'n_tokens_mistral': 6392, 'n_tokens_neox': 6231, 'n_words': 1425}