#!/usr/bin/env python
# aws_s3_to_s3 0.0.1 test suite
# Generated by dx-app-wizard.

import json
import os
import time
import unittest

import dxpy
import dxpy.app_builder
from subprocess import check_output, check_call, CalledProcessError

from dxpy.exceptions import DXAPIError
import dxpy.executable_builder  # work around for dx-toolkit import issue

DXPROJECT = os.environ["DX_PROJECT_CONTEXT_ID"]
src_dir = os.path.join(os.path.dirname(__file__), "..")
test_resources_dir = os.path.join(src_dir, "test", "resources")
CONFIG_FILE = {u'$dnanexus_link': 'file-F6JfjF00BJkG6GbJ9z308q5X'}


def _run_cmd(cmd, returnOutput=False):
    print cmd
    if returnOutput:
        output = check_output(
            cmd, shell=True, executable='/bin/bash').strip()
        # print output
        return output
    else:
        check_call(cmd, shell=True, executable='/bin/bash')


def _get_full_filenames(filelinks, s3prefix):
    rsp = [dxpy.api.file_describe(
        link['$dnanexus_link'],
        input_params={'fields': {'name': True, 'folder': True}})
        for link in filelinks]

    return [s3prefix + r['folder'] + '/' + r['name'] if r['folder'][-1] != '/' else s3prefix + r['folder'] + r['name']
            for r in rsp]


def config_setup(config_link):
    f_id = config_link['$dnanexus_link']
    dxpy.download_dxfile(f_id, "config")
    config_filepath = os.path.join(os.path.dirname(__file__), "config")
    os.environ['AWS_CONFIG_FILE'] = config_filepath


def makeInputs():
    # Files in Sub1 folder
    file_array = [{u'$dnanexus_link': 'file-F6KBVg00Bf3X7XyXK88kQQb5'},
                  {u'$dnanexus_link': 'file-F6KBQK80kX380x2z62989yQp'},
                  {u'$dnanexus_link': 'file-F6KBQgj04Zxx72Vj0ZXYZpXP'},
                  {u'$dnanexus_link': 'file-F6KBV5j0qfxBbFj262GQpqBJ'}]
    s3_bucket = "dnanexus-jenkins-vdev"
    workerlimit = 5
    f_struct = True
    additional_opt = "--sse"
    inputdict = {"config_file": CONFIG_FILE,
                 "f_ids": file_array,
                 "target_s3": s3_bucket,
                 "additional_upload_param": additional_opt,
                 "worker_max": workerlimit,
                 "conserve_structure": f_struct}

    return inputdict


class Testaws_Platform_to_s3(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        # Create aws folder upload name for reuse
        cls.awsfolder = "TestUpload_{0}".format(time.strftime("%b_%d_%Y"))
        # Make inputs.
        cls.base_input = makeInputs()
        # Set up AWS
        config_setup(CONFIG_FILE)
        cls.base_input["opt_dir"] = cls.awsfolder

        bundled_resources = dxpy.app_builder.upload_resources(src_dir)
        try:
            app_name = os.path.basename(os.path.abspath(src_dir)) + "_test"
        except OSError:
            app_name = "test_app"
        applet_basename = app_name + "_" + str(int(time.time()))
        cls.applet_id, _ignored_applet_spec = dxpy.app_builder.upload_applet(src_dir, bundled_resources, override_name=applet_basename, override_folder='/aws_transfer', project=DXPROJECT)
        print "Applet ID: {0}".format(cls.applet_id)

    @classmethod
    def tearDownClass(cls):
        # Clean up by removing the app we created.
        try:
            dxpy.api.container_remove_objects(dxpy.WORKSPACE_ID, {"objects": [cls.applet_id]})
        except DXAPIError as e:
            print "Error removing %s during cleanup; ignoring." % (cls.applet_id,)
            print e
        # Remove data files in S3 bucket under created folders
        delete_cmd = "aws s3 rm \"s3://{0}/{1}\" --recursive".format(cls.base_input["target_s3"], cls.base_input["opt_dir"])
        delete_rsp = _run_cmd(delete_cmd, True)
        print "Delete Summary:"
        print delete_rsp

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_base_input(self):
        """
        Tests the app with a basic input.

        Verify files are in S3
        """
        try:
            job = dxpy.DXApplet(
                self.applet_id).run(
                self.base_input,
                folder="/aws_transfer/aws_platform_to_s3_file_transfer")
            print "Waiting for %s to complete" % (job.get_id())
            job.wait_on_done()
        except dxpy.exceptions.DXJobFailureError as e:
            print "Job failed.  Review message for error type"
            self.fail(msg=e.message)
        else:
            print json.dumps(job.describe()["output"])
            # Verify files are on S3
            prefix = "s3://{0}/{1}".format(self.base_input["target_s3"], self.awsfolder)
            full_filenames = _get_full_filenames(self.base_input["f_ids"], prefix)
            aws_ls_cmds = ["aws s3 ls \"{0}\"".format(filename)
                           for filename in full_filenames]
            verify_fail = []
            for name, cmd in zip(full_filenames, aws_ls_cmds):
                try:
                    print 'Verifying: {0}'.format(name)
                    _run_cmd(cmd)
                except CalledProcessError:
                    verify_fail.append(name)

            if verify_fail:
                self.fail("Following uploads are not present on S3:  {0}".format(str(verify_fail)))


if __name__ == '__main__':
    unittest.main()
