package com.atlassian.stash.internal.web;

import com.atlassian.bitbucket.Product;
import com.atlassian.bitbucket.server.ApplicationMode;
import com.atlassian.bitbucket.server.ApplicationPropertiesService;
import com.atlassian.plugin.servlet.ServletContextFactory;
import com.atlassian.stash.internal.web.soy.StashSoyResponseBuilder;
import com.atlassian.stash.internal.web.util.CachePolicies;
import com.google.common.io.Resources;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.lang3.StringUtils;
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.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;
import java.util.GregorianCalendar;
import java.util.Set;
import java.util.TreeSet;

@Controller
@RequestMapping("/about")
public class AboutController {
    public static final String AUTHOR_FILE = "/AUTHORS.txt";
    public static final String VIEW = "bitbucket.internal.page.about";

    private final ApplicationPropertiesService appPropService;
    private final ServletContextFactory servletContextFactory;

    @Autowired
    public AboutController(ApplicationPropertiesService appPropService, ServletContextFactory servletContextFactory) {
        this.appPropService = appPropService;
        this.servletContextFactory = servletContextFactory;
    }

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView showAbout(HttpServletResponse response) throws MalformedURLException {
        CachePolicies.cacheForFourWeeks(response);

        // We now only generate this in the 'full' build, but we don't want the about page to _ever_ fall over
        // Ideally we just bundle the bom.csv file and generate the lgpl section on the fly
        boolean showLicenses = servletContextFactory.getServletContext().getResource("/static/page/about/lgpl.soy") != null;
        Set<String> authors = retrieveAuthors();

        return new StashSoyResponseBuilder(VIEW)
            .put("authors", authors)
            .put("showLicenses", showLicenses)
            .put("copyrightStartYear", Product.FIRST_YEAR_OF_RELEASE)
            .put("copyrightEndYear", calcEndCopyrightYear())
            .put("hideProfile", appPropService.getMode() == ApplicationMode.MIRROR)
            .build();
    }

    private int calcEndCopyrightYear() {
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(appPropService.getBuildTimestamp());
        return cal.get(GregorianCalendar.YEAR);
    }

    private Set<String> retrieveAuthors() {
        Set<String> authors = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        try {
            String file = Resources.getResource(AUTHOR_FILE).getFile();
            if (StringUtils.isNotEmpty(file)) {
                try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
                    LineIterator iterator = IOUtils.lineIterator(reader);
                    while (iterator.hasNext()) {
                        String line = StringUtils.trimToEmpty(iterator.next());
                        if (line.length() > 0 && line.charAt(0) != '#') {
                            authors.add(line);
                        }
                    }
                }
            }
        } catch (IllegalArgumentException | IOException e) {
            // the author file was not found or could not be read -> nothing to do
        }

        return authors;
    }

}
