#!/usr/bin/python

import os
import subprocess
import urllib
import urllib2
import tempfile
import json
import shutil
from time import localtime
import stat

# No trailing slash on this one
SAL_URL = "https://sal.yourcompany.com"
PUBLIC_KEY = "yourpublickeyhere"
PRIVATE_KEY = "yourreallyreallyreallylongprivatekeyhere"
PKG_IDENTIFIER = "com.yourcompany.sal_enrol"
SAL_PKG = "https://github.com/salopensource/sal/releases/download/v0.4.0/sal_scripts.pkg"
FACTER_PKG = "https://downloads.puppetlabs.com/mac/facter-latest.dmg"

# STOP EDITING HERE

def download_package(temp_dir, pkg_url):
    file_name = pkg_url.split('/')[-1]
    output_path = os.path.join(temp_dir, file_name)
    u = urllib2.urlopen(pkg_url)
    f = open(output_path, 'wb')
    meta = u.info()
    file_size = int(meta.getheaders("Content-Length")[0])
    print "Downloading: %s Bytes: %s" % (file_name, file_size)

    file_size_dl = 0
    block_sz = 8192
    while True:
        buffer = u.read(block_sz)
        if not buffer:
            break

        file_size_dl += len(buffer)
        f.write(buffer)
        status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
        status = status + chr(8)*(len(status)+1)
        print status,

    f.close()
    return output_path


def get_machine_groups():
    api_url = "%s/api/machine_groups/" % SAL_URL
    req = urllib2.Request(api_url)
    req.add_header('privatekey', PRIVATE_KEY)
    req.add_header('publickey', PUBLIC_KEY)
    response = urllib2.urlopen(req)
    output = response.read()
    return json.loads(output)

def mount_dmg(dmg):
    # Mount the dmg
    temp_mount = tempfile.mkdtemp()
    cmd = ['/usr/bin/hdiutil', 'attach', dmg, '-mountpoint', temp_mount]
    subprocess.call(cmd)
    return temp_mount

def unmount_dmg(path):
    cmd = ['/usr/bin/hdiutil', 'eject', path]
    subprocess.call(cmd)

def copy_packages(sourcePath, destPath):
    """
    Finds all packages in a specified directory and copies them to a specified directory
    """
    pkg_list = []
    for package in os.listdir(sourcePath):
        if package.endswith('.pkg') or package.endswith('.mpkg'):
            pkg = os.path.join(sourcePath, package)
            dest_file = os.path.join(destPath, os.path.basename(pkg))
            if os.path.isfile(pkg):
                shutil.copy(pkg, dest_file)
            else:
                shutil.copytree(pkg, dest_file)
            pkg_list.append(dest_file)
    return pkg_list

def main():
    # Make our tempdir
    temp_dir = tempfile.mkdtemp()
    pkg_root = os.path.join(temp_dir, 'package_root')
    if not os.path.exists(pkg_root):
        os.makedirs(pkg_root)
    # Download Sal package
    package = download_package(temp_dir, SAL_PKG)

    # Move it to the pkg root
    shutil.move(package, os.path.join(pkg_root,os.path.basename(package)))

    #Download FACTER_PKG
    facter = download_package(temp_dir, FACTER_PKG)

    # Mount Facter dmg
    facter_mount = mount_dmg(facter)

    # And copy out the .pkg
    facter_packages = copy_packages(facter_mount, pkg_root)

    # Unmount the dmg
    unmount_dmg(facter_mount)

    # Get all of the machine Groups
    machine_groups = get_machine_groups()

    script_dir = os.path.join(temp_dir, 'Scripts')
    now = localtime()
    version = "%04d.%02d.%02d" % (now.tm_year, now.tm_mon, now.tm_mday)
    # For Each machine group
    for group in machine_groups:
        pkg_name = '%s - %s.pkg' % (str(group['id']), group['name'])
        script = """#!/bin/bash
/usr/bin/defaults write $3/Library/Preferences/com.github.salopensource.sal ServerURL %s
/usr/bin/defaults write $3/Library/Preferences/com.github.salopensource.sal key %s
/usr/sbin/installer -pkg "/private/tmp/%s" -target $3
""" % (SAL_URL, group['key'], os.path.basename(package))
        # There is potentially going to be more than one package in here, loop over them all
        for facter_package in facter_packages:
            extra_script = """
/usr/sbin/installer -pkg "/private/tmp/%s" -target $3
""" % os.path.basename(facter_package)
            script = script + extra_script

        if not os.path.exists(script_dir):
            os.makedirs(script_dir)
        script_path = os.path.join(script_dir, 'postinstall')
        with open(script_path, "w") as fd:
            fd.write(script)
        os.chmod(script_path, 0755)

        pkg_output_path = os.path.join(os.getcwd(), pkg_name)
        cmd = ['/usr/bin/pkgbuild',
               "--root", pkg_root,
               "--identifier", PKG_IDENTIFIER,
               "--version", version,
               "--scripts", script_dir,
               "--install-location", "/private/tmp",
               pkg_output_path]
        subprocess.call(cmd)

        shutil.rmtree(script_dir)

if __name__ == '__main__':
    main()