/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.commonwl.viewer.web;

import org.commonwl.viewer.domain.GithubDetails;
import org.commonwl.viewer.domain.Workflow;
import org.commonwl.viewer.domain.WorkflowForm;
import org.commonwl.viewer.services.WorkflowFactory;
import org.commonwl.viewer.services.WorkflowFormValidator;
import org.commonwl.viewer.services.WorkflowRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.Valid;

@Controller
public class WorkflowController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final WorkflowFormValidator workflowFormValidator;
    private final WorkflowFactory workflowFactory;
    private final WorkflowRepository workflowRepository;

    /**
     * Autowired constructor to initialise objects used by the controller
     * @param workflowFormValidator Validator to validate the workflow form
     * @param workflowFactory Builds new Workflow objects
     */
    @Autowired
    public WorkflowController(WorkflowFormValidator workflowFormValidator,
                              WorkflowFactory workflowFactory,
                              WorkflowRepository workflowRepository) {
        this.workflowFormValidator = workflowFormValidator;
        this.workflowFactory = workflowFactory;
        this.workflowRepository = workflowRepository;
    }

    /**
     * Create a new workflow from the given github URL in the form
     * @param workflowForm The data submitted from the form
     * @param bindingResult Spring MVC Binding Result object
     * @return The workflow view with new workflow as a model
     */
    @PostMapping("/")
    public ModelAndView newWorkflowFromGithubURL(@Valid WorkflowForm workflowForm, BindingResult bindingResult) {
        logger.info("Retrieving workflow from Github: \"" + workflowForm.getGithubURL() + "\"");

        // Run validator which checks the github URL is valid
        GithubDetails githubInfo = workflowFormValidator.validateAndParse(workflowForm, bindingResult);

        if (bindingResult.hasErrors()) {
            // Go back to index if there are validation errors
            return new ModelAndView("index");
        } else {
            // The ID of the workflow to be redirected to
            String workflowID;

            // Check database for existing workflow
            Workflow existingWorkflow = workflowRepository.findByRetrievedFrom(githubInfo);
            if (existingWorkflow != null) {
                logger.info("Fetching existing workflow from DB");

                // Get the ID from the existing workflow
                workflowID = existingWorkflow.getID();
            } else {
                // New workflow from Github URL
                Workflow newWorkflow = workflowFactory.workflowFromGithub(githubInfo);

                // Runtime error
                if (newWorkflow == null) {
                    bindingResult.rejectValue("githubURL", "githubURL.parsingError");
                    return new ModelAndView("index");
                }

                // Save to the MongoDB database
                logger.info("Adding new workflow to DB");
                workflowRepository.save(newWorkflow);

                // Get the ID from the new workflow
                workflowID = newWorkflow.getID();
            }

            // Redirect to the workflow
            return new ModelAndView("redirect:/workflows/" + workflowID);
        }
    }

    /**
     * Display a page for a particular workflow
     * @param workflowID The ID of the workflow to be retrieved
     * @return The workflow view with the workflow as a model
     */
    @RequestMapping(value="/workflows/{workflowID}")
    public ModelAndView getWorkflow(@PathVariable String workflowID){

        // Get workflow from database
        Workflow workflowModel = workflowRepository.findOne(workflowID);

        // 404 error if workflow does not exist
        if (workflowModel == null) {
            throw new WorkflowNotFoundException();
        }

        // Display this model along with the view
        return new ModelAndView("workflow", "workflow", workflowModel);

    }
}

@@ -1296,143 +1296,84 @@
 ork.
-stereotype.Controller;%0Aimport org.springframework.validation.BindingResult;%0Aimport org.springframework.web.bind.annotation.PathVariab
+core.io.FileSystemResource;%0Aimport org.springframework.stereotype.Control
 le
+r
 ;%0Aim
@@ -1401,39 +1401,32 @@
 ork.
-web.bind.annotation.PostMapping
+validation.BindingResult
 ;%0Aim
@@ -1470,30 +1470,17 @@
 otation.
-RequestMapping
+*
 ;%0Aimport
@@ -1544,24 +1544,120 @@
 vax.
-validation.Valid
+servlet.http.HttpServletResponse;%0Aimport javax.validation.Valid;%0Aimport java.io.File;%0Aimport java.io.IOException
 ;%0A%0A@
@@ -5362,11 +5362,1177 @@
 ;%0A%0A    %7D
+%0A%0A    /**%0A     * Download the Research Object Bundle for a particular workflow%0A     * @param workflowID The ID of the workflow to download%0A     */%0A    @RequestMapping(value = %22/workflows/%7BworkflowID%7D/download%22,%0A                    method = RequestMethod.GET,%0A                    produces = %22application/vnd.wf4ever.robundle+zip%22)%0A    @ResponseBody%0A    public FileSystemResource getFile(@PathVariable(%22workflowID%22) String workflowID,%0A                                      HttpServletResponse response) %7B%0A%0A        // Get workflow from database%0A        Workflow workflowModel = workflowRepository.findOne(workflowID);%0A%0A        // 404 error if workflow does not exist%0A        if (workflowModel == null) %7B%0A            throw new WorkflowNotFoundException();%0A        %7D%0A%0A        // Set a sensible default file name for the browser%0A        response.setHeader(%22Content-Disposition%22, %22attachment; filename=bundle.zip;%22);%0A%0A        // Serve the file from the local filesystem%0A        File bundleDownload = new File(workflowModel.getRoBundle());%0A        logger.info(%22Serving download for %22 + bundleDownload.toString());%0A        return new FileSystemResource(bundleDownload);%0A    %7D
 %0A%7D%0A

Add RO bundle download URL to controller