package cz.muni.reddening;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.multipart.MultipartFile;

import java.io.IOException;
import java.sql.SQLException;

/**
 * Spring Controller which catches requests on URLs and responds to them
 */
@Controller
public class ControllerClassMVC {
    private static final Logger log = LoggerFactory.getLogger(ControllerClassMVC.class);

    @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
    @Autowired
    private Configuration configuration;

    /**
     * Estimation by values
     * @param x is the first coordinate in degrees
     * @param y is the second coordinate in degrees
     * @param distance is the third coordinate in parsecs
     * @param law is the reddening law/map we use
     * @param frame is the coordinate system we use
     * @return correct reddening output or error message of the script
     */
    @RequestMapping(value = "/check", method =  RequestMethod.POST)
    @ResponseBody
    public String check(@RequestParam final float x, @RequestParam final float y,
                        @RequestParam final float distance, @RequestParam final String law,
                        @RequestParam final String frame) {
        return (new CalcHandler(law, frame, String.valueOf(x),
                String.valueOf(y), String.valueOf(distance))).runScript(configuration);
    }

    /**
     * Estimation from file input
     * @param law is the reddening law/map we use
     * @param file is the file we got from user
     * @param frame is coordinate frame used for calculations
     * @return the content of output file
     * @throws IOException if unable to process the input file
     */
    @RequestMapping(value = "/checkF", method =  RequestMethod.POST)
    @ResponseBody
    public String checkFile(@RequestParam String law,
                            @RequestParam MultipartFile file,
                            @RequestParam String frame) throws IOException {
        return (new FileHandler(file, law, frame)).output(configuration);

    }

    /**
     *  Queries the database to show user individual reddening values of stars
     * @param x is the first coordinate in degrees
     * @param y is the second coordinate in degrees
     * @param dist is the third coordinate in parsecs
     * @param order specifies if we sort records ascending or descending
     * @param sort is the attribute by which we sort
     * @param limit is the number from which we show queries
     * @param offset is the number from which we dont show queries
     * @return output of the query we make in JSON format
     */
    @SuppressWarnings("SpellCheckingInspection")
    @RequestMapping(value = "/query")
    @ResponseBody
    public String queryDatabase(@RequestParam final float x, @RequestParam final float y,
                          @RequestParam final float dist, @RequestParam final String order,
                          @RequestParam final String sort, @RequestParam final int limit,
                                @RequestParam final int offset) {
        if (!(order.toLowerCase().equals("asc")
                || order.toLowerCase().equals("desc"))) {
            log.error("SQL invalid offset");
            return "Invalid input data";
        }
        switch (sort.toLowerCase()) {
            case "eucldist" :
            case "x" :
            case "y" :
            case "distance_from_the_sun":
            case "reddening" :
            case "identification":
                break;
            default :
                log.error("SQL invalid sort attribute");
                return "Invalid input data";
        }
        try {
            return (new SQLHandler(x, y, dist, sort, order,
                    offset, limit)).execute(configuration);
        } catch (SQLException e) {
            log.error("error, sql exception", e);
        } catch (ClassNotFoundException e) {
            log.error("error, class not found exception", e);
        }
        return "Error getting data from database";
    }

    /**
     * Loads base site of the application
     * @return application page
     */
    @RequestMapping(value = "")
    public String baseLoad() {
        return "index.html";
    }

    /**
     * Reloads the application
     * @return application page
     */
    @RequestMapping(value = "/index.html")
    public String reload() {
        return "index.html";
    }
}
