#!/usr/bin/env python3
#
# Software License Agreement (BSD)
#
# @author    Mike Purvis <mpurvis@clearpathrobotics.com>
# @author    Chris Iverach-Brereton <civerachb@clearpathrobotics.com>
# @copyright (c) 2014-2020, Clearpath Robotics, Inc., All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that
# the following conditions are met:
# * Redistributions of source code must retain the above copyright notice, this list of conditions and the
#   following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
#   following disclaimer in the documentation and/or other materials provided with the distribution.
# * Neither the name of Clearpath Robotics nor the names of its contributors may be used to endorse or
#   promote products derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# @usage    download_flycap arch library_dest os_code_name
#           e.g. download_flyap x64_64 /path/to/somewhere xenial

import http.cookiejar
import io
import logging
import shutil
import subprocess
import sys
import tarfile
import urllib.request, urllib.parse, urllib.error
import urllib.request, urllib.error, urllib.parse
import os

logging.basicConfig(level=logging.INFO)

URL_TEMPLATES = {
    'deb': 'https://packages.clearpathrobotics.com/stable/flir/Flycap2/flycapture2-2.13.3.31-{arch}-pkg_Ubuntu{version}.tgz',
    'src': 'https://packages.clearpathrobotics.com/stable/flir/Flycap2/flycapture.2.13.3.31_{arch}_Ubuntu{version}.tar.gz'
}

ARCHS = {
    'x86_64': {
        'linux_arch': 'amd64',
        'past': '16.04',
        'current': '18.04',
        'future': '20.04',
        'type': 'deb',
        'debs': [
            'flycap-2.13.3.31_amd64.deb',
            'flycapture-doc-2.13.3.31_amd64.deb',
            'libflycapture-2.13.3.31_amd64.deb',
            'libflycapture-2.13.3.31_amd64-dev.deb',
            'libflycapture-c-2.13.3.31_amd64.deb',
            'libflycapture-c-2.13.3.31_amd64-dev.deb',
            'libflycapturegui-2.13.3.31_amd64.deb',
            'libflycapturegui-2.13.3.31_amd64-dev.deb',
            'libflycapturegui-c-2.13.3.31_amd64.deb',
            'libflycapturegui-c-2.13.3.31_amd64-dev.deb',
            'libflycapturevideo-2.13.3.31_amd64.deb',
            'libflycapturevideo-2.13.3.31_amd64-dev.deb',
            'libflycapturevideo-c-2.13.3.31_amd64.deb',
            'libflycapturevideo-c-2.13.3.31_amd64-dev.deb',
            'libmultisync-2.13.3.31_amd64.deb',
            'libmultisync-c-2.13.3.31_amd64.deb',
            'updatorgui-2.13.3.31_amd64.deb'
        ],
        'shared_library': 'usr/lib/libflycapture.so.2.13.3.31',
        'folder_name': 'flycapture2-2.13.3.31-amd64'
    },
    'i386': {
        'linux_arch': 'i386',
        'past': '16.04',
        'type': 'deb',
        'debs': [
            'flycap-2.13.3.31_i386.deb',
            'flycapture-doc-2.13.3.31_i386.deb',
            'libflycapture-2.13.3.31_i386.deb',
            'libflycapture-2.13.3.31_i386-dev.deb',
            'libflycapture-c-2.13.3.31_i386.deb',
            'libflycapture-c-2.13.3.31_i386-dev.deb',
            'libflycapturegui-2.13.3.31_i386.deb',
            'libflycapturegui-2.13.3.31_i386-dev.deb',
            'libflycapturegui-c-2.13.3.31_i386.deb',
            'libflycapturegui-c-2.13.3.31_i386-dev.deb',
            'libflycapturevideo-2.13.3.31_i386.deb',
            'libflycapturevideo-2.13.3.31_i386-dev.deb',
            'libflycapturevideo-c-2.13.3.31_i386.deb',
            'libflycapturevideo-c-2.13.3.31_i386-dev.deb',
            'libmultisync-2.13.3.31_i386.deb',
            'libmultisync-c-2.13.3.31_i386.deb',
            'updatorgui-2.13.3.31_i386.deb'
        ],
        'shared_library': 'usr/lib/libflycapture.so.2.13.3.31',
        'folder_name': 'flycapture2-2.13.3.31-i386'
    },
    'armv7': {
        'linux_arch': 'armhf',
        'past': '16.04',
        'current': '18.04',
        'future': '20.04',
        'type': 'src',
        'shared_library': 'usr/lib/libflycapture.so.2.13.3.31',
        'folder_name': 'flycapture.2.13.3.31_armhf'
    },
    'armv8': {
        'linux_arch': 'arm64',
        'past': '16.04',
        'current': '18.04',
        'future': '20.04',
        'type': 'src',
        'shared_library': 'usr/lib/libflycapture.so.2.13.3.31',
        'folder_name': 'flycapture.2.13.3.31_arm64'
    }
}

OS_LIBRARY_VERSION = {
  'jessie': 'past',
  'xenial': 'past',
  'bionic': 'current',
  'focal': 'future'
}

arch, library_dest, os_code_name = sys.argv[1:]
library_version = OS_LIBRARY_VERSION.get(os_code_name, 'current')

logging.info("CPU architecture is %s", arch)
logging.info("OS code name is %s", os_code_name)
archive_url = URL_TEMPLATES[ARCHS[arch]['type']].format(arch=ARCHS[arch]['linux_arch'], version=ARCHS[arch][library_version])

logging.info("Downloading SDK archive from {0}...".format(archive_url))
cj = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
resp = opener.open(archive_url)

logging.info('Unpacking tarball...')
fileobj=resp.read()
with tarfile.open(mode="r:gz", fileobj=io.BytesIO(fileobj)) as tar:
    tar.extractall()

if ARCHS[arch]['type'] == 'src':
    shared_library = ARCHS[arch]['shared_library']
    folder_name = ARCHS[arch]['folder_name']
    logging.info("Copying ARM libs from: %s to %s", shared_library, library_dest)

    # Creating (current_folder)/usr folder to eliminate need for if branching in
    # Download_Flycap.cmake. x86 library is packaged different (contained in /usr
    # folder) and in ARM there is no /usr folder, therefore we create it.
    os.mkdir(os.path.join(os.getcwd(), "usr"))

    # For every folder/file, move it into the /usr folder we just created.
    for filename in os.listdir(os.path.join(os.getcwd(), folder_name)):
        shutil.move(os.path.join(os.getcwd(), folder_name, filename),
                    os.path.join(os.getcwd(), "usr/", filename))
    os.rmdir(folder_name)

    # now we do some thing for include files; move them into the /usr folder as well
    include_path = os.path.join(os.getcwd(), "usr/include")
    include_files = os.listdir(include_path)
    flycap_folder = "flycapture"
    os.mkdir(os.path.join(include_path, flycap_folder))

    for files in include_files:
        if files.endswith(".h"):
            shutil.move(os.path.join(include_path, files), os.path.join(include_path, flycap_folder))

else:
    debs = ARCHS[arch]['debs']
    folder_name = ARCHS[arch]['folder_name']

    for deb in debs:
        logging.info("Extracting: %s", deb)
        subprocess.check_call(['dpkg', '--extract', os.path.join(folder_name, deb), '.'])

logging.info("Copying shared library.")
shutil.copyfile(ARCHS[arch]['shared_library'], library_dest)
