"""Plugin for testing that data staging works."""

import os
import tempfile
from typing import List, TextIO, Tuple
from arcnagios import arcutils
from arcnagios.nagutils import CRITICAL, NagiosReport
from arcnagios.ce.jobplugin import JobPlugin, StagingSpec
from arcnagios.utils import log_process_error

def _split_url_urloptions(urlspec: str) -> Tuple[str, List[str]]:
    if ';' in urlspec:
        xs = urlspec.split(';')
        return (xs[0], xs[1:])
    else:
        return (urlspec, [])

class StagingJobPlugin(JobPlugin):

    def staged_inputs(self, workdir: str) -> List[StagingSpec]:

        def to_spec(index: int, url: str) -> StagingSpec:
            url, urloptions = _split_url_urloptions(url)
            filename = '%s-in-%d' % (self.test_name, index)
            return StagingSpec(filename, url, urloptions)

        urls = self.getconf_strlist('staged_inputs', default = [])
        return [to_spec(i, u) for i, u in zip(range(0, len(urls)), urls)]

    def staged_outputs(self, workdir: str) -> List[StagingSpec]:

        def to_spec(index: int, url: str) -> StagingSpec:
            url, urloptions = _split_url_urloptions(url)
            filename = '%s-out-%d' % (self.test_name, index)
            return StagingSpec(filename, url, urloptions)

        urls = self.getconf_strlist('staged_outputs', default = [])
        return [to_spec(i, u) for i, u in zip(range(0, len(urls)), urls)]

    def upload_test_file(self, url: str) -> None:
        try:
            fd, path = tempfile.mkstemp(prefix = 'tmp-check_arcce_submit-',
                                        text = True)
            fh = os.fdopen(fd, 'w')
            fh.write('This file was uploaded for use by ARC-CE '
                     'staging probes.\n')
            fh.close()
        except OSError as exn:
            self.log.warning('Failed to create a temporary file '
                             'for upload, using /dev/null: %s' % exn)
            path = '/dev/null'

        self.log.info('Uploading %s to %s.', path, url)
        r = self.arcclient.arccp(path, url)
        if path != '/dev/null':
            os.unlink(path)
        if r.is_error():
            self.log.warning('Failed to create %s: %s', url, r.get_error())

    def upload_missing_test_files(self) -> None:
        urls = self.getconf_strlist('upload_if_missing', default = [])
        for url in urls:
            try:
                if self.arcclient.arcls(url).get() == []:
                    self.upload_test_file(url)
            except arcutils.CalledProcessError as exn:
                log_process_error(self.log, exn, prefix = 'arcls')
                self.upload_test_file(url)

    def write_script(self, fh: TextIO, workdir: str) -> None:
        self.upload_missing_test_files()
        fh.write('# Test "%s" handled by the "staging" job-plugin.\n'
                 % self.test_name)
        for staging_spec in self.staged_outputs(workdir):
            fh.write('hostname >%s\n' % staging_spec.filename)
        fh.write('\n')

    def check(
            self, report: NagiosReport, jobdir: str, stored_urls: List[str]
        ) -> None:
        for url in stored_urls:
            try:
                filenames = self.arcclient.arcls(url).get()
                if filenames == []:
                    report.log.error('Could not list %s.', url)
                    report.update_status(CRITICAL)
                elif len(filenames) > 1:
                    report.log.warning('Got multiple entries from %s:', url)
                    for filename in filenames:
                        report.log.warning('  %s', filename)
            except arcutils.CalledProcessError as exn:
                log_process_error(report.log, exn)
                report.update_status(CRITICAL)
