/**
 * OLAT - Online Learning and Training<br>
 * http://www.olat.org
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); <br>
 * you may not use this file except in compliance with the License.<br>
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing,<br>
 * software distributed under the License is distributed on an "AS IS" BASIS, <br>
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
 * See the License for the specific language governing permissions and <br>
 * limitations under the License.
 * <p>
 * Code originally based on de.bps.course.nodewizard.CopyStructureWizardFactoryImpl
 * <p>
 * Modified and adapted by<br>
 * University of Innsbruck, http://www.uibk.ac.at
 * <p>
 */
package de.bps.course.nodewizard;

import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.tree.TreeNode;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.wizard.Step;
import org.olat.core.gui.control.generic.wizard.StepRunnerCallback;
import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
import org.olat.core.gui.control.generic.wizard.StepsRunContext;
import org.olat.core.gui.translator.PackageTranslator;
import org.olat.core.gui.translator.Translator;
import org.olat.core.id.Identity;
import org.olat.core.util.nodes.INode;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.course.CourseFactory;
import org.olat.course.export.CourseFragmentEnvironmentMapper;
import org.olat.course.nodes.CourseNode;
import org.olat.course.run.environment.CourseEnvironment;
import org.olat.course.tree.CourseEditorTreeModel;

import de.bps.course.nodewizard.coursenode.ICourseNodeCopyConfigurator;

/**
 *
 * Description:<br>
 * CopyStructure Wizard callback
 *
 * <P>
 * based on code extracted from CopyStructureWizardFactoryImpl
 * Initial Date: 16.12.2010 <br>
 *
 * @author Daniel Haag (based on code by @author bja)
 *
 */
public class CopyStructureWizardStepRunnerCallback implements StepRunnerCallback {

	private WizardStepProcess process;

	private CourseFragmentEnvironmentMapper courseFragmentEnvironmentMapper;

	public CourseFragmentEnvironmentMapper getCourseFragmentEnvironmentMapper() {
		return courseFragmentEnvironmentMapper;
	}

	@Override
	public Step execute(final UserRequest ureq, final WindowControl wControl, final StepsRunContext runContext) {
		boolean hasChanges = false;
		final Translator translator = new PackageTranslator(this.getClass().getPackage().getName(), ureq.getLocale());
		courseFragmentEnvironmentMapper = new CourseFragmentEnvironmentMapper();

		process = (WizardStepProcess) runContext.get("stepProcess");

		// if "copy all" is selected, we handle the whole course folder
		if (process.getCopyAll()) {
			copyAllFiles();
		}

		final TreeNode rootNode = process.getCourseNodeTreeModel().getRootNode();

		if (rootNode.getChildCount() > 0) {
			hasChanges = true;
			for (int i = 0; i < rootNode.getChildCount(); i++) {
				addChildNode(ureq.getIdentity(), process.getTargetCourse().getRunStructure().getRootNode(), rootNode.getChildAt(i));
			}
			// after all the selected nodes are added to the target course, configure all the added nodes and apply the node id mapping
			courseFragmentEnvironmentMapper.getNodeSourceIds().stream()
				.forEach(srcId -> configureNode(ureq.getIdentity(), srcId, translator));
			CourseFactory.saveCourseEditorTreeModel(process.getTargetCourse().getResourceableId());
		}
		return hasChanges ? StepsMainRunController.DONE_MODIFIED : StepsMainRunController.DONE_UNCHANGED;
	}

	private void copyAllFiles() {
		final VFSContainer srcRootFolder = process.getSrcCourse().getCourseEnvironment().getCourseFolderContainer();
		final VFSContainer targetRootFolder = process.getTargetCourse().getCourseEnvironment().getCourseFolderContainer();
		targetRootFolder.copyContentOf(srcRootFolder);
	}

	private void addChildNode(final Identity fallbackIdentity, CourseNode targetParentNode, final INode node) {
		final CourseNode srcCourseNode = process.getSrcCourse().getRunStructure().getNode(node.getIdent());
		final CourseNode selectedTargetParentNode;
		if (process.getSelectedKeys().contains(node.getIdent())) {
			// add course node
			CourseEditorTreeModel targetEditorTreeModel = process.getTargetCourse().getEditorTreeModel();
			final boolean isNewTitle = targetEditorTreeModel.getNodeById(node.getIdent()) != null;
			final CourseNode targetCourseNode = srcCourseNode.createInstanceForCopy(isNewTitle, process.getTargetCourse(),fallbackIdentity);

			// Remove the parent and the children references as the new node ends up in the editortreemodel,
			// where the tree structure is not in the Course Nodes but in the EditorTreeNodes.
			targetCourseNode.setParent(null);
			targetCourseNode.removeAllChildren();
			//------

			targetEditorTreeModel.addCourseNode(targetCourseNode, targetParentNode);
			courseFragmentEnvironmentMapper.addNodeIdentKeyPair(srcCourseNode.getIdent(), targetCourseNode.getIdent());
			selectedTargetParentNode = targetCourseNode;
		} else {
			selectedTargetParentNode = targetParentNode;
		}
		// handle children
		for (int i = 0; i < node.getChildCount(); i++) {
			addChildNode(fallbackIdentity, selectedTargetParentNode, node.getChildAt(i));
		}
	}

	private void configureNode(final Identity fallbackIdentity, String srcNodeId, final Translator translator) {

		final CourseEnvironment srcCourseEnv = process.getSrcCourse().getCourseEnvironment();
		final CourseEnvironment targetCourseEnv = process.getTargetCourse().getCourseEnvironment();

		final CourseNode srcCourseNode = process.getSrcCourse().getRunStructure().getNode(srcNodeId);
		final CourseNode targetCourseNode = process.getTargetCourse().getEditorTreeModel()
				.getCourseNode(courseFragmentEnvironmentMapper.getNodeTargetIdent(srcNodeId));

		// we do not let the individual nodes copy their files if the copy all
		// option is selected as all the files should be there already.
		final boolean canCopyToCourseFolder = !process.getCopyAll();

		final ICourseNodeCopyConfigurator cncc = CopyStructureWizardFactory.getInstance().getCourseNodeCopyConfigurator(
				fallbackIdentity, srcCourseEnv, targetCourseEnv, srcCourseNode,
				targetCourseNode, courseFragmentEnvironmentMapper, canCopyToCourseFolder);

		cncc.configure();
		cncc.updateNodeReferences();
	}


}