package org.iri_research.renkan.controller;

import java.util.HashMap;
import java.util.Map;

import org.iri_research.renkan.Constants;
import org.iri_research.renkan.Constants.EditMode;
import org.iri_research.renkan.RenkanException;
import org.iri_research.renkan.RenkanProperties;
import org.iri_research.renkan.models.Project;
import org.iri_research.renkan.repositories.ProjectsRepository;
import org.iri_research.renkan.repositories.SpacesRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/p")
public class RenkanController {

    private final Logger logger = LoggerFactory
            .getLogger(RenkanController.class);

    @Autowired
    private ProjectsRepository projectsRepository;

    @Autowired
    private SpacesRepository spacesRepository;

    private void checkCowebkey(String cowebkey, Project project,
            Constants.EditMode editMode) {
        if (cowebkey == null || cowebkey.isEmpty()) {
            throw new HttpClientErrorException(HttpStatus.BAD_REQUEST,
                    "Cowebkey missing");
        }
        try {
            if (!project.checkKey(cowebkey, editMode)) {
                throw new HttpClientErrorException(HttpStatus.BAD_REQUEST,
                        "Bad cowebkey");
            }
        } catch (RenkanException e) {
            throw new HttpServerErrorException(
                    HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

    @RequestMapping(value = "/copy", method = RequestMethod.POST, produces = { "application/json;charset=UTF-8" })
    public @ResponseBody
    Project copyProject(@RequestParam(value = "project_id") String projectId) {

        if (projectId == null || projectId.length() == 0) {
            throw new IllegalArgumentException(
                    "RenkanContoller.renkanProject.copyProject: Project id is null or empty.");
        }
        Project project = this.projectsRepository.findOne(projectId);
        if (project == null) {
            throw new HttpClientErrorException(HttpStatus.NOT_FOUND, "Project "
                    + projectId + " not found for copyProject.");
        }

        Project newProject = this.projectsRepository.copy(project,
                project.getTitle() + " (copy)");

        return newProject;
    }

    @RequestMapping(value = "/{project_id}", method = RequestMethod.GET, produces = {
            "text/html;charset=UTF-8", "!image/*" })
    public ModelAndView renkanProject(
            @PathVariable(value = "project_id") String project_id,
            @RequestHeader(value = "Accept") String accept_header,
            @RequestParam(value = "cowebkey") String cowebkey)
            throws HttpMediaTypeNotSupportedException {

        this.logger.debug("renkanProject : " + project_id + " Accept : "
                + accept_header != null ? accept_header : "" + ", cowebkey: "
                + cowebkey != null ? cowebkey : "");

        if (project_id == null || project_id.length() == 0) {
            throw new IllegalArgumentException(
                    "RenkanContoller.renkanProject: Project id is null or empty.");
        }

        Project project = this.projectsRepository.findOne(project_id);

        if (project == null) {
            throw new HttpClientErrorException(HttpStatus.NOT_FOUND, "Project "
                    + project_id + " not found.");
        }

        this.checkCowebkey(cowebkey, project, EditMode.EDITION);

        Map<String, Object> model = new HashMap<String, Object>();
        model.put("coweb_debug", Boolean.parseBoolean(RenkanProperties
                .getInstance().getProperty("renkan.coweb.debug", "false")));
        model.put("coweb_websockets", Boolean.parseBoolean(RenkanProperties
                .getInstance().getProperty("renkan.coweb.websocket", "true")));
        model.put("project", project);
        model.put("space", spacesRepository.findOne(project.getSpaceId()));

        return new ModelAndView("renkanProjectEdit", model);
    }

    @RequestMapping(value = "/pub/{project_id}", method = RequestMethod.GET, produces = {
            "text/html;charset=UTF-8", "!image/*" })
    public String renkanPublishProject(Model model,
            @PathVariable(value = "project_id") String project_id,
            @RequestParam(value = "cowebkey") String cowebkey) {
        if (project_id == null || project_id.length() == 0) {
            throw new IllegalArgumentException(
                    "RenkanContoller.renkanProject: Project id is null or empty.");
        }

        Project project = this.projectsRepository.findOne(project_id);
        if (project == null) {
            throw new HttpClientErrorException(HttpStatus.NOT_FOUND, "Project "
                    + project_id + " not found.");
        }

        this.checkCowebkey(cowebkey, project, EditMode.READ_ONLY);

        model.addAttribute("project", project);
        model.addAttribute("space",
                spacesRepository.findOne(project.getSpaceId()));

        return "renkanProjectPublish";
    }

}
