#!/bin/sh

########################################################################################
#
#  postinstall script for winclone to create partition based on size and then
#  restore a winclone image on it.  All the settings are passed in via the
#  $1/WinclonePayload/settings.sh.  settings.sh should contain these items:
#
#   $existing: If existing is 1, then will check to make sure the partition exists, is NTFS or MSDOS, and will
#              then use that to restore the Winclone image onto
#   $create:   If create, a bootcamp partition will
#              be created.  This requires a size (either bytes or percent). requires either $size or
#              $percent to be set.
#
#
#   $slice: if $existing, this must be set to the slice on the select volume to
#           restore to.
#
#    $size: size in kbytes of the new Windows partition in "create" mode.
#
#    $percent: size in percent of the new Windows partition in "create" mode.
#
#
########################################################################################

whole_disk() { 

            diskutil cs list -plist > ${DIR}/cs.plist

            UUID=`/usr/libexec/PlistBuddy  -c "Print :CoreStorageLogicalVolumeGroups:0:CoreStoragePhysicalVolumes:$1:CoreStorageUUID" ${DIR}/cs.plist`

            if [ -z "$UUID" ]; then
                echo "Could not get UUID of a physical volume"
                wholedisk=""
                return
            fi

            diskutil cs info -plist $UUID > ${DIR}/disk.plist

            PHYSICAL_DISK=`/usr/libexec/PlistBuddy -c "Print :DeviceIdentifier" ${DIR}/disk.plist`
            echo physical partition of selected volume is $PHYSICAL_DISK
            if [ -z "$PHYSICAL_DISK" ]; then

                "Could not get a device that the physical disk is on.  exiting"
                wholedisk=""
            else
            	wholedisk=`diskutil info -plist "${PHYSICAL_DISK}" |grep -A 1 ParentWholeDisk|tail -1|sed 's|.*<string>\(.*\)</string>.*|\1|'`
	    	fi
}


if [ ! -f "$1/Contents/Resources/settings.sh" ] ; then
    echo "Could not find setting file at $1/Contents/Resources/settings.sh.  Quitting"
    exit -1

fi
source "$1/Contents/Resources/settings.sh"

echo "Creating or discovering bootcamp partition"

if [ -z "${existing}" -a -z "${create}" ] ; then

    echo "Neither existing nor create specified. Exiting."
    exit -1
fi
if [ "$existing" ] && [ $existing -eq 1 ]; then

    if [ -z "$slice" ] ; then
        echo "  Could not find ${slice}.  Exiting"
        exit -1
    fi

    echo "  Using slice ${slice}"

    apfs_active=0
    is_apfs=`diskutil info "$3" | grep apfs`
    if [ $? -eq 0 ] ; then
        echo "Selected volume is apfs"
        apfs_active=1
    fi

    core_storage_active=0

    echo "checking for core storage....."
    is_core_storage=`diskutil cs info "$3"`
    if [ $? -eq 0 ] ; then
        echo "Selected volume is core storage"
        core_storage_active=1
    fi

    if [ $core_storage_active -eq 1 ]; then

        echo "we have core storage.  Probing..."


        DISKFOUND=`diskutil cs list|grep 'CoreStorage logical volume groups'|sed "s|.*(\(.*\) found.*|\1|"`

        if [ $DISKFOUND != "1" ]; then
            echo "more than 1 cs groups.  not supported.  Exiting"
            exit -1
        fi

        DIR=`mktemp -d /tmp/XXXXXXXXXXXX`

        if [ -z "$DIR" ]; then
            echo "could not make temp dir!  Exiting"
            exit -1
        fi

        if [ "${slice}" == "first_windows"  ]; then
            echo "Finding Microsoft Basic Data on disk"
            whole_disk 0

            win_partition=$(diskutil list ${wholedisk} | grep 'Microsoft Basic Data' | sed 's/.*\(disk.*[0123456789]*\).*/\1/g')
            if [ -z "${win_partition}" ] ; then
                echo "No Microsoft Basic Data on first disk, setting whole disk to second disk (fusion)"
                whole_disk 1
                if [ -z "${wholedisk}" ] && [ "${create}" ] && [ $create -eq 1 ] ; then
                    echo "Could not find specified partition. Continuing on to create partition"
                    restore_device=""
                    wholedisk=""
                    slice=""
                else
                    echo "Could not find any second disk, exiting"
                    exit -1
                fi
            fi

        else
            echo "Disk slice specified. Checking to see what whole disk it is on"

            whole_disk 0

            restore_device="/dev/${wholedisk}s${slice}"

            echo "restore_device is $restore_device"

            echo "Discovered whole disk of ${wholedisk}"

            fs_type=`diskutil info -plist "${restore_device}" | grep -A 1 FilesystemType |tail -1|sed 's|.*<string>\(.*\)</string>.*|\1|'`
            echo "Whole disk has filesystem of type ${fs_type}"

            if [ -z $fs_type ]  ; then
                echo "No filesystem type discovered. Setting to second whole disk (Fusion)"
                whole_disk 1
                if [ -z "${wholedisk}" ] && [ "${create}" ] && [ $create -eq 1 ] ; then
                    echo "Could not find specified partition. Continuing on to create partition"
                    restore_device=""
		            wholedisk=""
		            slice=""
                elif [ -z "${wholedisk}" ];  then
                    echo "Could not find any second disk, exiting"
                    exit -1
                fi

                echo "whole disk (0) is ${wholedisk}"

            elif  [ ! $fs_type = "ntfs" ] && [ ! $fs_type = "msdos" ] && [ ! $fs_type = "exfat" ] ; then
                echo "Found Microsoft Basic Data but filesystem is not ntfs, msdos, or exfat. Setting whole disk to second disk (Fusion)"
                whole_disk 1
                if [ -z "${wholedisk}" ] && [ -z "$create" ] ; then
                    echo "Not second disk found. Exiting."
                    exit -1
                fi

                if [ -z "${wholedisk}" ] && [ "${create}" ] && [ $create -eq 1 ] ; then

                    echo "Could not find specified partition. Continuing on to create partition"
                    restore_device=""
                    wholedisk=""
                    slice=""

                elif [ -z "${wholedisk}" ];  then
                    echo "Could not find any second disk, exiting"
                    exit -1
                else
                    echo "whole disk (1) is ${wholedisk}"
                fi
            fi
        fi



    elif [ $apfs_active -eq 1 ] ; then
        echo "APFS found.  Discovering whole disk"
        apfs_wholedisk=`diskutil info -plist "$3" |grep -A 1 ParentWholeDisk|tail -1|sed 's|.*<string>\(.*\)</string>.*|\1|'`


        if [ -z "$apfs_wholedisk" ] ; then

            echo "  Could not find whole disk from $3.  Quitting"
            exit -1

        fi

        wholedisk=`diskutil apfs list "$apfs_wholedisk" | grep 'APFS Physical Store Disk' | sed 's|.*\(disk[0123456789].*\)s.*|\1|g'`

        if [ -z "$wholedisk" ] ; then

            echo "  Could not find wholedisk (APFS) from $3.  Quitting"
            exit -1

        fi

        echo "whole disk is $wholedisk"


    else
        echo "not core storage or APFS, so checking for standard"
        wholedisk=`diskutil info -plist "$3" |grep -A 1 ParentWholeDisk|tail -1|sed 's|.*<string>\(.*\)</string>.*|\1|'`


        if [ -z "${wholedisk}" ] ; then

            echo "Could not find whole disk...exiting"
            exit -1
        fi

    fi


    if [ "${slice}" == "first_windows" ]; then

        echo "Discovering first windows volume on ${wholedisk}."

        win_partition=$(diskutil list ${wholedisk} | grep 'Microsoft Basic Data' | sed 's/.*\(disk.*[0123456789]*\).*/\1/g')
        if [ "${win_partition}" ] ; then
            restore_device="/dev/${win_partition}"

            if [ $(echo "$restore_device" | wc -l ) -gt 1 ]; then
                echo "There was more than 1 Microsoft Basic Data partition found on ${wholedisk}: ${restore_device}"
                exit -1
            fi

            echo "Found ${restore_device}"
        else
	        echo "No Windows partition found, checking second disk (Fusion)"
		    whole_disk 1
	        win_partition=$(diskutil list ${wholedisk} | grep 'Microsoft Basic Data' | sed 's/.*\(disk.*[0123456789]*\).*/\1/g')
       		if [ "${win_partition}" ] ; then
            		restore_device="/dev/${win_partition}"
		        if [ $(echo "$restore_device" | wc -l ) -gt 1 ]; then
               			echo "There was more than 1 Microsoft Basic Data partition found on ${wholedisk}: ${restore_device}"
                		exit -1
            		fi
            		echo "Found ${restore_device}"
        	fi

        fi
        echo restoring to device $restore_device

    elif [ "${wholedisk}" ] && [ "${slice}" ] ; then
        restore_device="/dev/${wholedisk}s${slice}"

        if [ -e "${restore_device}" ] ; then
            echo "restoring to device ${restore_device}"
        elif [ "$create" ] && [ $create -eq 1 ]; then
            echo "Partition ${restore_device} not found. Continuing..."
            wholedisk=""
            restore_device=""

        else
            echo "Specified partition ${restore_device} does not exist"
        fi

    else
        echo "whole disk or slice not specified"
    fi


fi

if [ -z "$restore_device" ] && [ "$create" ] && [ $create -eq 1 ] ; then
    echo "Mode: Create Partition"

    echo "    checking for existing bootcamp partitions..."
    existing_bc_partitions=`diskutil list|grep 'Microsoft Basic Data'|wc -l`

    if [ $existing_bc_partitions -gt 0 ] ; then
        echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        echo "A windows partition already exists so a new one does not have be created.  Remove any existing FAT or NTFS partitions or unplug external drives that have a FAT / NTFS partition. Here is the partition found:"
        diskutil list|grep 'Microsoft Basic Data'
        echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        exit -1
    fi

    echo "    checking for core storage..."
    core_storage_active=0
    is_core_storage=`diskutil cs info "$3"`
    if [ $? -eq 0 ] ; then
        echo "Selected volume is core storage"
        core_storage_active=1
    fi


    echo "    checking for apfs..."
    apfs_active=0

    is_apfs=`diskutil info "$3" | grep apfs`
    if [ $? -eq 0 ] ; then
        echo "Selected volume is apfs"
        apfs_active=1
    fi



    echo "    checking size..."

    partition_size=`diskutil info -plist "$3" |grep -A 1 TotalSize|tail -1|sed 's|.*<integer>\(.*\)</integer>.*|\1|'`


    echo "  Making sure that the partition to split is JHFS+ or APFS"

    fs_type=`diskutil info -plist "$3" |grep -A 1 FilesystemName|tail -1|sed 's|.*<string>\(.*\)</string>.*|\1|'`

    if [ -z "${fs_type}" ] ; then
        echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        echo "  Could not find $3.  Exiting."
        echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

        exit -1
    fi

    if [ "${fs_type}" = "Journaled HFS+" -o  $core_storage_active == 1 -o $apfs_active == 1 ] ; then

        echo "  Filesystem is Journaled HFS+, core storage or apfs so we are good to try and split it..."

        if [[ -n "$size" ]] ; then

            echo "Creating by size"

            hfs_size=`diskutil info -plist "$3" |grep -A 1 TotalSize|tail -1|sed 's|.*<integer>\(.*\)</integer>.*|\1|'`
            new_hfs_size="$(($hfs_size-$size))b"
            echo hfs_size is $hfs_size
            echo new_hfs_size is $new_hfs_size

        elif [[ -n "$percent" ]] ; then

           
            if [ $core_storage_active == 1 -o $apfs_active == 1 ] ; then
				convert_percent=`echo $percent |sed 's|%|/100|g'`
				echo "Converting percentage from ${percent} to ${convert_percent}"
				new_percent=`echo "scale=0;$partition_size * $convert_percent "|bc -l`
				new_hfs_size="${new_percent}b"
				echo "New Mac size is ${new_hfs_size}"

		    else
		
	        	new_hfs_size=$percent
		    fi

        else

            echo "  You must specify either size or percent.  Exiting."
            exit -1
        fi


        if [ -z "$3" ] ; then

            echo "  Could not find $3.  Quitting"
            exit -1

        fi

        if [ -z "$new_hfs_size" ] ; then

            echo "  Could not find ${new_hfs_size}.  Quitting"
            exit -1

        fi



        if [ $core_storage_active == 1  ] ; then

			echo creating from core storage
            restore_device=`diskutil cs resizestack "$3" "${new_hfs_size}" MS-DOS DOS 0b|grep 'FAT32 clusters'|sed 's/.*\(disk[0123456789]\{1,\}s[0123456789]\{1,\}\).*/\1/'`

            if [ -z "$restore_device" ] ; then

                echo "  Could not find ${restore_device}.  Quitting"
                exit -1

            fi
            restore_device="/dev/${restore_device}"

            echo "  Completed resizing.  New device is ${restore_device}"

            wholedisk=`diskutil info -plist "$restore_device" |grep -A 1 ParentWholeDisk|tail -1|sed 's|.*<string>\(.*\)</string>.*|\1|'`

            echo "whole disk is ${wholedisk}"
            if [ -z "${wholedisk}" ] ; then

                echo "Could not find whole disk...exiting"
                exit -1
            fi


        elif [ $apfs_active == 1 ] ; then

			echo creating from APFS
			
			   apfs_wholedisk=`diskutil info -plist "$3" |grep -A 1 ParentWholeDisk|tail -1|sed 's|.*<string>\(.*\)</string>.*|\1|'`
			   
			   
            if [ -z "$apfs_wholedisk" ] ; then

                echo "  Could not find whole disk from $3.  Quitting"
                exit -1

            fi

			   
			   restore_device=`diskutil apfs resizeContainer "${apfs_wholedisk}" "${new_hfs_size}" MS-DOS DOS 0b|grep 'FAT32 clusters'|sed 's/.*\(disk[0123456789]\{1,\}s[0123456789]\{1,\}\).*/\1/'`

            if [ -z "$restore_device" ] ; then

                echo "  Could not find ${restore_device}.  Quitting"
                exit -1

            fi
            restore_device="/dev/${restore_device}"

            echo "  Completed resizing.  New device is ${restore_device}"

            wholedisk=`diskutil info -plist "$restore_device" |grep -A 1 ParentWholeDisk|tail -1|sed 's|.*<string>\(.*\)</string>.*|\1|'`

            echo "whole disk is ${wholedisk}"
            if [ -z "${wholedisk}" ] ; then

                echo "Could not find whole disk...exiting"
                exit -1
            fi



			   
        else

            restore_device=`diskutil resizeVolume "$3" "${new_hfs_size}" MS-DOS DOS 0b|grep "Microsoft Basic Data"|sed 's/.*\(disk.*s.*\)/\1/'`

            if [ -z "$restore_device" ] ; then

                echo "  Could not find ${restore_device}.  Quiting"
                exit -1

            fi

            restore_device="/dev/${restore_device}"

            echo "  Completed resizing.  New device is ${restore_device}"

            wholedisk=`diskutil info -plist "$3" |grep -A 1 ParentWholeDisk|tail -1|sed 's|.*<string>\(.*\)</string>.*|\1|'`

            echo "whole disk is ${wholedisk}"
            if [ -z "${wholedisk}" ] ; then

                echo "Could not find whole disk...exiting"
                exit -1
            fi

        fi
    else
        echo "Specified partition $3  is not Journaled HFS+"
        return -1

    fi

fi

echo "================================================================================"
echo "Restoring....  Progress log is at /tmp/winclone_package.log"
echo "================================================================================"
echo "  checking to see if partition ${restore_device} exists"

fs_type=`diskutil info -plist ${restore_device} | grep -A 1 FilesystemType |tail -1|sed 's|.*<string>\(.*\)</string>.*|\1|'`

if [ -z "${fs_type}" ] ; then

    echo "  could not find device ${restore_device}"
    exit -1

fi

if [ $fs_type = "ntfs" ] || [ $fs_type = "msdos" ] || [ $fs_type = "exfat" ] ; then

    echo "  Filesystem is $fs_type so we are good to restore to it..."

    cd "$1"/Contents/Resources/*.winclone/

    if [ -n "$winpe" ]; then 

        mode_flag="-w"

    else 
        mode_flag="--self-extract"
    fi
    if [ -n "$wim_index" ] ; then 
        wim_index_arg="-i ${wim_index}"
    else
        wim_index_arg="-i 1"
    fi
    if [ $bootmode -eq 1 ]; then
        echo Forcing boot mode to legacy
        ./winclone ${mode_flag} -l -p ${restore_device} ${wim_index_arg}  2>&1 
    elif [ $bootmode -eq  2 ]; then
        echo Forcing boot mode to efi
        ./winclone ${mode_flag} -e  -p ${restore_device} ${wim_index_arg} 2>&1 
    else
        ./winclone ${mode_flag} -p ${restore_device} ${wim_index_arg}  2>&1
    fi

    if [ $? -ne 0 ] ; then
        echo "Failed restoring to ${restore_device}."
        exit -1
    fi

    if [ -f "$1/Contents/Resources/Sysprep/unattend.xml" -o  "$1/Contents/Resources/Sysprep/SetupComplete.cmd" ] ; then
        echo "found unattend.xml or SetupComplete.cmd so preparing resources"
    
        bootcamp_mounted=$(./winclone -m ${restore_device})

        if [ $? -ne 0 ] ; then
            echo "failed mounting ${restore_device} read/write."
            exit -1
        fi
		
		if [ -f "$1/Contents/Resources/Sysprep/unattend.xml" ]; then
		
	        echo "making unattend directory"
	        mkdir -p "${bootcamp_mounted}/Windows/Panther/Unattend"
	
	        echo "setting computer name"
	        hostname=$(hostname -s)
            sc_computername=$(scutil --get ComputerName| tr -d ' ' |tr -d '\n' )
	        macaddress=$(ifconfig en0|grep ether|sed "s/.*ether \(.*\):\(.*\):\(.*\):\(.*\):\(.*\):\(.*\)/\1\2\3\4\5/")
	        serial=$(system_profiler SPHardwareDataType | grep 'Serial Number (system)' | awk '{print $NF}')
	        resolved=${computer_name/\%HOSTNAME\%/${hostname}}
	        resolved=${resolved/\%MACADDRESS\%/${macaddress}}
            resolved=${resolved/\%COMPUTERNAME\%/${sc_computername}}
            resolved=${resolved/\%SERIAL\%/${serial}}
	        truncated_computer_name=$(echo $resolved | sed 's/\(...............\).*/\1/')
	        echo computer name is $truncated_computer_name
	        sed "s/%COMPUTERNAME%/${truncated_computer_name}/g" "$1/Contents/Resources/Sysprep/unattend.xml"   > "${bootcamp_mounted}/Windows/Panther/Unattend/unattend.xml"

	        echo "copying resources"
	        cp -R "$1/Contents/Resources/Sysprep/Winclone" "${bootcamp_mounted}"
	    fi
	        
    fi
    if [ -f "$1/Contents/Resources/Sysprep/SetupComplete.cmd" ] ; then
        echo "found SetupComplete"
        echo "making Windows\Setup\Scripts directory if needed"
        mkdir -p "${bootcamp_mounted}/Windows/Setup/Scripts"
        echo "copying SetupComplete.cmd"
        cp "$1/Contents/Resources/Sysprep/SetupComplete.cmd" "${bootcamp_mounted}/Windows/Setup/Scripts/"


    fi

	echo "mounting read only"
	
	diskutil unmount ${restore_device}
	diskutil mount ${restore_device}

    if [ $set_startup_disk -eq 1 ]; then
        echo setting startup disk
        if [ $bootmode -eq 1 ]; then
            echo setting startup disk to legacy
            ./winclone -b 2 -p ${restore_device} 2>&1
        elif [ $bootmode -eq  2 ]; then
            echo setting startup disk to efi
            ./winclone -b 1 -p ${restore_device} 2>&1
        else
            echo setting startup disk to autodetect
        ./winclone -b 0 -p ${restore_device} 2>&1 

        fi
    fi
else

    echo "   Filesystem is not ntfs, msdos or exfat!  Exiting."
    exit -1

fi



exit 0
