package com.atlassian.bitbucket.internal.ssh.scm;

import com.atlassian.bitbucket.Product;
import com.atlassian.bitbucket.help.HelpPathService;
import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.internal.ssh.server.DefaultingExitCodeCallback;
import com.atlassian.bitbucket.scm.ScmRequestCheckService;
import com.atlassian.bitbucket.scm.ssh.SshScmRequest;
import com.atlassian.bitbucket.ssh.command.SshCommand;
import com.atlassian.bitbucket.throttle.ResourceBusyException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

class ScmRequestSshCommand implements SshCommand {

    private static final Logger log = LoggerFactory.getLogger(ScmRequestSshCommand.class);

    private final SshScmRequest scmRequest;
    private final DefaultingExitCodeCallback exitCodeCallback;
    private final HelpPathService helpPathService;
    private final I18nService i18nService;
    private final ScmRequestCheckService scmRequestCheckService;

    ScmRequestSshCommand(SshScmRequest scmRequest, DefaultingExitCodeCallback exitCodeCallback,
                         HelpPathService helpPathService, I18nService i18nService,
                         ScmRequestCheckService scmRequestCheckService) {
        this.exitCodeCallback = exitCodeCallback;
        this.helpPathService = helpPathService;
        this.i18nService = i18nService;
        this.scmRequest = scmRequest;
        this.scmRequestCheckService = scmRequestCheckService;
    }

    @Override
    public void cancel() {
        scmRequest.cancel();
    }

    @Override
    public int run() throws IOException {
        if (scmRequestCheckService.checkActionAllowed(scmRequest)) {
            log.trace("{}: Request has passed checking and will be processed", scmRequest);

            try {
                scmRequest.handleRequest();
            } catch (ResourceBusyException e) {
                try {
                    scmRequest.sendError(
                            i18nService.getMessage("bitbucket.scm.throttled"),
                            i18nService.getMessage("bitbucket.scm.throttled.detail", Product.NAME));
                } catch (IOException e1) {
                    log.info("Could not send error message to client: '{}'", e1.getMessage());
                }
                log.info(String.format(
                        "A %s request was denied due to heavy server load. Please see %s for performance guidelines.",
                        e.getResourceName(), helpPathService.getPageUrl("bitbucket.help.scaling")));
                return 1;
            }
        } else {
            log.debug("{}: Request has failed a check and will not be processed", scmRequest);
        }
        return exitCodeCallback.getExitCode();
    }
}
