/*
* Catroid: An on-device visual programming system for Android devices
* Copyright (C) 2010-2016 The Catrobat Team
* (<http://developer.catrobat.org/credits>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* An additional term exception under section 7 of the GNU Affero
* General Public License, version 3, is available at
* http://developer.catrobat.org/license_additional_term
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.catrobat.catroid.ui.controller;
import android.app.Activity;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import org.catrobat.catroid.ProjectManager;
import org.catrobat.catroid.R;
import org.catrobat.catroid.common.Constants;
import org.catrobat.catroid.common.LookData;
import org.catrobat.catroid.common.SoundInfo;
import org.catrobat.catroid.content.Script;
import org.catrobat.catroid.content.Sprite;
import org.catrobat.catroid.content.bricks.BackPackedListData;
import org.catrobat.catroid.content.bricks.BackPackedVariableData;
import org.catrobat.catroid.content.bricks.Brick;
import org.catrobat.catroid.content.bricks.FormulaBrick;
import org.catrobat.catroid.content.bricks.PlaySoundBrick;
import org.catrobat.catroid.content.bricks.PointToBrick;
import org.catrobat.catroid.content.bricks.ScriptBrick;
import org.catrobat.catroid.content.bricks.SetLookBrick;
import org.catrobat.catroid.content.bricks.UserBrick;
import org.catrobat.catroid.content.bricks.UserBrickParameter;
import org.catrobat.catroid.content.bricks.UserListBrick;
import org.catrobat.catroid.content.bricks.UserScriptDefinitionBrick;
import org.catrobat.catroid.content.bricks.UserScriptDefinitionBrickElement;
import org.catrobat.catroid.content.bricks.UserVariableBrick;
import org.catrobat.catroid.formulaeditor.DataContainer;
import org.catrobat.catroid.formulaeditor.UserList;
import org.catrobat.catroid.formulaeditor.UserVariable;
import org.catrobat.catroid.ui.BackPackActivity;
import org.catrobat.catroid.ui.ScriptActivity;
import org.catrobat.catroid.utils.ToastUtil;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public final class BackPackScriptController {
public static final String TAG = BackPackScriptController.class.getSimpleName();
private static final BackPackScriptController INSTANCE = new BackPackScriptController();
private BackPackScriptController() {
}
public static BackPackScriptController getInstance() {
return INSTANCE;
}
public List<Script> backpack(String groupName, List<Brick> checkedBricks, boolean addToHiddenBackpack, Sprite
spriteToBackpack) {
Iterator<Brick> iterator = checkedBricks.iterator();
List<Script> scriptsToAdd = new ArrayList<>();
while (iterator.hasNext()) {
Brick currentBrick = iterator.next();
if (currentBrick instanceof ScriptBrick) {
Script original = ((ScriptBrick) currentBrick).getScriptSafe();
Script scriptToAdd = original.copyScriptForSprite(
ProjectManager.getInstance().getCurrentSprite());
ProjectManager.getInstance().checkCurrentScript(scriptToAdd, false);
scriptToAdd.setCommentedOut(original.isCommentedOut());
for (Brick brickOfScript : scriptToAdd.getBrickList()) {
brickOfScript.storeDataForBackPack(spriteToBackpack);
}
scriptsToAdd.add(scriptToAdd);
}
}
if (!scriptsToAdd.isEmpty()) {
if (addToHiddenBackpack) {
BackPackListManager.getInstance().addScriptToHiddenBackpack(groupName, scriptsToAdd);
} else {
BackPackListManager.getInstance().addScriptToBackPack(groupName, scriptsToAdd);
}
}
return scriptsToAdd;
}
public void unpack(String selectedScriptGroupBackPack, boolean deleteUnpackedItems, boolean
handleInsertFromScriptBackPack, Activity activity, boolean fromHiddenBackPack) {
List<Script> scriptsInGroup;
if (fromHiddenBackPack) {
scriptsInGroup = BackPackListManager.getInstance().getHiddenBackpackedScripts().get(selectedScriptGroupBackPack);
} else {
scriptsInGroup = BackPackListManager.getInstance().getBackPackedScripts().get(selectedScriptGroupBackPack);
}
if (scriptsInGroup == null) {
Log.d(TAG, "Attempted to unpack a not existing (maybe previously deleted) script group");
return;
}
Integer numberOfBricks = 0;
for (Script backPackedScript : scriptsInGroup) {
Script newScript = backPackedScript.copyScriptForSprite(ProjectManager.getInstance().getCurrentSprite());
for (Brick brickOfScript : newScript.getBrickList()) {
handleBackPackedBricksWithAdditionalData(brickOfScript, deleteUnpackedItems);
}
ProjectManager.getInstance().getCurrentSprite().addScript(newScript);
numberOfBricks += backPackedScript.getBrickList().size();
if (deleteUnpackedItems) {
if (fromHiddenBackPack) {
BackPackListManager.getInstance().removeItemFromScriptHiddenBackpack(selectedScriptGroupBackPack);
} else {
BackPackListManager.getInstance().removeItemFromScriptBackPack(selectedScriptGroupBackPack);
}
}
if (handleInsertFromScriptBackPack) {
String textForUnPacking = activity.getResources().getQuantityString(R.plurals
.unpacking_items_plural, 1);
ToastUtil.showSuccess(activity, selectedScriptGroupBackPack + " " + textForUnPacking);
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(activity);
sharedPreferences.edit().putInt(Constants.NUMBER_OF_BRICKS_INSERTED_FROM_BACKPACK, numberOfBricks).commit();
((BackPackActivity) activity)
.returnToScriptActivity(ScriptActivity.FRAGMENT_SCRIPTS);
}
}
}
private void handleBackPackedBricksWithAdditionalData(Brick brickOfScript, boolean deleteUnpackedItems) {
if (brickOfScript instanceof SetLookBrick) {
handleLookBrickUnpacking(brickOfScript, deleteUnpackedItems);
} else if (brickOfScript instanceof PlaySoundBrick) {
handleSoundBrickUnpacking(brickOfScript, deleteUnpackedItems);
} else if (brickOfScript instanceof UserVariableBrick) {
handleVariableBrickUnpacking(brickOfScript);
} else if (brickOfScript instanceof UserListBrick) {
handleVariableListUnpacking(brickOfScript);
} else if (brickOfScript instanceof PointToBrick) {
handlePointToBrickUnpacking(brickOfScript, deleteUnpackedItems);
} else if (brickOfScript instanceof UserBrick) {
handleUserBrickUnpacking(brickOfScript, deleteUnpackedItems);
} else if (brickOfScript instanceof FormulaBrick) {
handleFormulaBrickUnpacking(brickOfScript);
}
}
private void handleFormulaBrickUnpacking(Brick brickOfScript) {
FormulaBrick brick = (FormulaBrick) brickOfScript;
for (BackPackedListData backPackedData : brick.getBackPackedListData()) {
if (backPackedData.userList != null) {
updateListsInDataContainer(backPackedData, backPackedData.userList);
}
}
for (BackPackedVariableData backPackedData : brick.getBackPackedVariableData()) {
if (backPackedData.userVariable != null) {
updateVariablesInDataContainer(backPackedData, backPackedData.userVariable);
}
}
}
private void handleLookBrickUnpacking(Brick brickOfScript, boolean deleteUnpackedItems) {
SetLookBrick brick = (SetLookBrick) brickOfScript;
LookData newLookData = LookController.getInstance().unpack(brick.getLook(), deleteUnpackedItems, true);
if (newLookData != null) {
brick.setLook(newLookData);
}
}
private void handleSoundBrickUnpacking(Brick brickOfScript, boolean deleteUnpackedItems) {
PlaySoundBrick brick = (PlaySoundBrick) brickOfScript;
SoundInfo newSoundInfo = SoundController.getInstance().unpack(brick.getSound(), deleteUnpackedItems, true);
if (newSoundInfo != null) {
brick.setSoundInfo(newSoundInfo);
}
}
private void handleVariableBrickUnpacking(Brick brickOfScript) {
UserVariableBrick brick = (UserVariableBrick) brickOfScript;
BackPackedVariableData backPackedData = brick.getBackPackedData();
if (brick.getUserVariable() == null) {
brick.setUserVariable(backPackedData.userVariable);
}
UserVariable variable = updateVariablesInDataContainer(backPackedData, brick.getUserVariable());
brick.setUserVariable(variable);
}
private void handleVariableListUnpacking(Brick brickOfScript) {
UserListBrick brick = (UserListBrick) brickOfScript;
BackPackedListData backPackedData = brick.getBackPackedData();
if (brick.getUserList() == null) {
brick.setUserList(backPackedData.userList);
}
updateListsInDataContainer(backPackedData, brick.getUserList());
}
private void handlePointToBrickUnpacking(Brick brickOfScript, boolean deleteUnpackedItems) {
PointToBrick brick = (PointToBrick) brickOfScript;
Sprite unpackedPointToSprite = BackPackSpriteController.getInstance().unpack(brick.getPointedObject(),
deleteUnpackedItems, true, true, false);
brick.setPointedObject(unpackedPointToSprite);
}
private void handleUserBrickUnpacking(Brick brickOfScript, boolean deleteUnpackedItems) {
UserBrick brick = (UserBrick) brickOfScript;
Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite();
UserBrick clonedPrototypeUserBrick = (UserBrick) brick.clone();
clonedPrototypeUserBrick.updateUserBrickParametersAndVariables();
currentSprite.addUserBrick(clonedPrototypeUserBrick);
for (Brick brickOfUserScript : brick.getDefinitionBrick().getUserScript().getBrickList()) {
handleBackPackedBricksWithAdditionalData(brickOfUserScript, deleteUnpackedItems);
}
setUserBrickElementReferences(brick);
brick.updateUserBrickParametersAndVariables();
}
private void setUserBrickElementReferences(UserBrick brick) {
UserScriptDefinitionBrick definitionBrick = brick.getDefinitionBrick();
List<UserScriptDefinitionBrickElement> userScriptDefinitionBrickElementList = definitionBrick.getUserScriptDefinitionBrickElements();
Iterator<UserBrickParameter> userBrickParameterIterator = brick.getUserBrickParameters().iterator();
for (UserScriptDefinitionBrickElement element : userScriptDefinitionBrickElementList) {
if (element.isVariable() && userBrickParameterIterator.hasNext()) {
UserBrickParameter parameter = userBrickParameterIterator.next();
parameter.setElement(element);
}
}
}
private UserVariable updateVariablesInDataContainer(BackPackedVariableData backPackedData, UserVariable userVariable) {
ProjectManager projectManager = ProjectManager.getInstance();
DataContainer dataContainer = projectManager.getCurrentScene().getDataContainer();
UserVariable unpackedVariable = null;
switch (backPackedData.userVariableType) {
case DataContainer.USER_VARIABLE_SPRITE:
Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite();
unpackedVariable = dataContainer.addSpriteVariableIfDoesNotExist(userVariable.getName(), currentSprite);
break;
case DataContainer.USER_VARIABLE_PROJECT:
unpackedVariable = dataContainer.findUserVariable(userVariable.getName(),
dataContainer.getProjectVariables());
if (unpackedVariable == null) {
unpackedVariable = dataContainer.addProjectUserVariable(userVariable.getName());
}
break;
case DataContainer.USER_VARIABLE_USERBRICK:
UserBrick userBrick = ProjectManager.getInstance().getCurrentUserBrick();
if (userVariable != null) {
unpackedVariable = dataContainer.addUserBrickVariableToUserBrickIfNotExists(userBrick, userVariable.getName(),
userVariable.getValue());
}
break;
}
return unpackedVariable;
}
private void updateListsInDataContainer(BackPackedListData backPackedData, UserList userList) {
ProjectManager projectManager = ProjectManager.getInstance();
DataContainer dataContainer = projectManager.getCurrentScene().getDataContainer();
switch (backPackedData.userListType) {
case DataContainer.USER_LIST_SPRITE:
Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite();
dataContainer.addSpriteListIfDoesNotExist(userList.getName(), currentSprite);
break;
case DataContainer.USER_LIST_PROJECT:
if (dataContainer.findUserList(userList.getName(),
dataContainer.getProjectLists()) == null) {
dataContainer.addProjectUserList(userList.getName());
}
break;
}
}
}