#!/bin/bash

CamomileInstrument="Camomile"
CamomileEffect="CamomileFx"
CamomileLV2="Camomile_LV2"

AppleVst3Extension=vst3
AppleAuExtension=component
AppleLV2Extension=dylib
LinuxVst3Extension=vst3
LinuxLV2Extension=so

ThisPath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

unameOut="$(uname -s)"
case "${unameOut}" in
    Linux*)     machine=Linux;;
    Darwin*)    machine=Mac;;
    CYGWIN*)    machine=Cygwin;;
    MINGW*)     machine=MinGw;;
    *)          machine="UNKNOWN:${unameOut}"
esac

################################################################################
#                       POSTS                                                  #
################################################################################

post_error() {
    echo -e "\033[31m"$1"\033[0m"
}

post_log() {
    echo -e "\033[2;30m"$1"\033[0m"
}

################################################################################
#                       GET PLUGIN TYPE                                        #
################################################################################

plugin_get_type() {
    local plugin_dir=$1
    local plugin_name=$2
    local textfile=$plugin_dir/$plugin_name.txt
    if [ -f "$textfile" ]; then
        while IFS='' read -r line || [[ -n "$line" ]]; do
            local wline=($line)
            if [ "${wline[0]}" == "type" ]; then
                type=${wline[1]}
                type="${type%?}"
                echo ${type}
                return
            fi
        done < "$textfile"
        echo "undefined"
    fi
    echo "error"
}

################################################################################
#                       GENERATE LV2 PLUGIN MAC                                #
################################################################################

generate_plugin_lv2_mac() {
    local camo_name=$CamomileLV2
    local plugin_input_dir=$1
    local plugin_output_dir=$2
    local plugin_name=$(basename $1)

    # Check if the folder exists and get the type of the plugin
    if [ ! -d $plugin_input_dir ]; then
        post_error "$plugin_input_dir is not a directory"
        return
    fi

    # Get the dynamic libraries
    if [ -f "$ThisPath/$camo_name.$AppleLV2Extension" ]; then
        if [ -d "$plugin_output_dir/$plugin_name.lv2" ]; then
            rm -rf "$plugin_output_dir/$plugin_name.lv2"
        fi

        mkdir "$plugin_output_dir/$plugin_name.lv2"
        mkdir "$plugin_output_dir/$plugin_name.lv2/Contents"
        mkdir "$plugin_output_dir/$plugin_name.lv2/Contents/Resources"
        cp -f "$ThisPath/$CamomileLV2.$AppleLV2Extension" "$plugin_output_dir/$plugin_name.lv2/$plugin_name.$AppleLV2Extension"
        cp -rf "$plugin_input_dir"/* "$plugin_output_dir/$plugin_name.lv2/Contents/Resources"
        for subfile in $(find "$plugin_output_dir/$plugin_name.lv2")
        do
          xattr -d com.apple.quarantine "$subfile"
        done
        xattr -d com.apple.quarantine "$ThisPath/lv2_file_generator"
        "$ThisPath/lv2_file_generator" "$plugin_output_dir/$plugin_name.lv2/$plugin_name.$AppleLV2Extension" $plugin_name
        mv -f "$PWD/manifest.ttl" "$plugin_output_dir/$plugin_name.lv2/manifest.ttl"
        if [ -f "$PWD/presets.ttl" ]; then
            mv -f "$PWD/presets.ttl" "$plugin_output_dir/$plugin_name.lv2/presets.ttl"
        fi
        mv -f "$PWD/$plugin_name.ttl" "$plugin_output_dir/$plugin_name.lv2/$plugin_name.ttl"
        post_log "$plugin_output_dir/$plugin_name.lv2"
    else
        post_error "$camo_name.$AppleLV2Extension is not available"
    fi
}

################################################################################
#                       GENERATE AU PLUGIN MAC                                 #
################################################################################

au_get_plugin_code_mac() {
    local plugin_dir=$1
    local plugin_name=$2
    local textfile=$plugin_dir/$plugin_name.txt
    if [ -f "$textfile" ]; then
        while IFS='' read -r line || [[ -n "$line" ]]; do
            local wline=($line)
            if [ "${wline[0]}" == "code" ]; then
                local word=${wline[1]}
                echo ${word::4}
                return
            fi
        done < "$textfile"
        echo "undefined"
    fi
    echo "error"
}

au_get_plugin_manufacturer_mac() {
    local plugin_dir=$1
    local plugin_name=$2
    local textfile=$plugin_dir/$plugin_name.txt
    if [ -f "$textfile" ]; then
        while IFS='' read -r line || [[ -n "$line" ]]; do
            local wline=($line)
            if [ "${wline[0]}" == "manufacturer" ]; then
                echo "${wline[*]}" | sed -e 's/manufacturer \(.*\);/\1/'
                return
            fi
        done < "$textfile"
        echo "undefined"
        return
    fi
    echo "error"
}

generate_plugin_au_mac() {
    local camo_name
    local plugin_input_dir=$1
    local plugin_output_dir=$2
    local plugin_name=$(basename $1)

    # Check if the folder exists and get the type of the plugin
    if [ -d $plugin_input_dir ]; then
        local plugin_type=$(plugin_get_type $plugin_input_dir $plugin_name)
        if [ "$plugin_type" == "error" ]; then
            post_error "$plugin_input_dir does not contain description text file $plugin_name.txt"
            return
        elif [[ "$plugin_type" == *"instrument"* ]]; then
            camo_name=$CamomileInstrument
        elif [[ "$plugin_type" == *"effect"* ]]; then
            camo_name=$CamomileEffect
        else
            post_error "$plugin_type is not a valid"
            return
        fi
    else
        post_error "$plugin_input_dir is not a directory"
        return
    fi

    local code=$(au_get_plugin_code_mac $plugin_input_dir $plugin_name)
    local manufacturer=$(au_get_plugin_manufacturer_mac $plugin_input_dir $plugin_name)
    if [ "$code" == "undefined" ]; then
        post_error "plugin code undefined"
        return
    elif [ "$code" == "undefined" ]; then
        post_error "$plugin_input_dir does not contain description text file $plugin_name.txt"
        return
    fi

    # Get the dynamic libraries
    if [ -d "$ThisPath/$camo_name.$AppleAuExtension" ]; then
        if [ -d "$plugin_output_dir/$plugin_name.$AppleAuExtension" ]; then
            rm -rf "$plugin_output_dir/$plugin_name.$AppleAuExtension"
        fi

        cp -rf "$ThisPath/$camo_name.$AppleAuExtension" $plugin_output_dir/$plugin_name.$AppleAuExtension
        cp -rf "$plugin_input_dir"/* "$plugin_output_dir/$plugin_name.$AppleAuExtension/Contents/Resources"
        xattr -d com.apple.quarantine "$plugin_output_dir/$plugin_name.$AppleAuExtension"
        for subfile in $(find "$plugin_output_dir/$plugin_name.$AppleAuExtension/Contents")
        do
          xattr -d com.apple.quarantine "$subfile"
        done
        plutil -replace CFBundleName -string $plugin_name "$plugin_output_dir/$plugin_name.$AppleAuExtension/Contents/Info.plist"
        plutil -replace CFBundleDisplayName -string $plugin_name "$plugin_output_dir/$plugin_name.$AppleAuExtension/Contents/Info.plist"

        plutil -replace AudioComponents.name -string "${manufacturer//[$'\t\r\n']}: $plugin_name" "$plugin_output_dir/$plugin_name.$AppleAuExtension/Contents/Info.plist"
        plutil -replace AudioComponents.subtype -string $code "$plugin_output_dir/$plugin_name.$AppleAuExtension/Contents/Info.plist"

        post_log "$plugin_output_dir/$plugin_name.$AppleAuExtension"
    else
        post_error "$camo_name.$AppleAuExtension is not available"
    fi
}

#############################################s###################################
#                       GENERATE VST3 PLUGIN MAC                               #
################################################################################

generate_plugin_vst3_mac() {
    local camo_name
    local plugin_input_dir=$1
    local plugin_output_dir=$2
    local plugin_name=$(basename $1)

    # Check if the folder exists and get the type of the plugin
    if [ -d $plugin_input_dir ]; then
        local plugin_type=$(plugin_get_type $plugin_input_dir $plugin_name)
        if [ "$plugin_type" == "error" ]; then
            post_error "$plugin_input_dir does not contain description text file $plugin_name.txt"
            return
        elif [[ "$plugin_type" == *"instrument"* ]]; then
            camo_name=$CamomileInstrument
        elif [[ "$plugin_type" == *"effect"* ]]; then
            camo_name=$CamomileEffect
        else
            post_error "$plugin_type is not a valid"
            return
        fi
    else
        post_error "$plugin_input_dir is not a directory"
        return
    fi

    # Get the dynamic libraries
    if [ -d "$ThisPath/$camo_name.$AppleVst3Extension" ]; then
        if [ -d "$plugin_output_dir/$plugin_name.$AppleVst3Extension" ]; then
            rm -rf "$plugin_output_dir/$plugin_name.$AppleVst3Extension"
        fi

        cp -rf "$ThisPath/$camo_name.$AppleVst3Extension" "$plugin_output_dir/$plugin_name.$AppleVst3Extension"
        cp -rf "$plugin_input_dir"/* "$plugin_output_dir/$plugin_name.$AppleVst3Extension/Contents/Resources"
        xattr -d com.apple.quarantine "$plugin_output_dir/$plugin_name.$AppleVst3Extension"
        for subfile in $(find "$plugin_output_dir/$plugin_name.$AppleVst3Extension/Contents")
        do
          xattr -d com.apple.quarantine "$subfile"
        done
        plutil -replace CFBundleName -string $plugin_name "$plugin_output_dir/$plugin_name.$AppleVst3Extension/Contents/Info.plist"
        plutil -replace CFBundleDisplayName -string $plugin_name "$plugin_output_dir/$plugin_name.$AppleVst3Extension/Contents/Info.plist"
        post_log "$plugin_output_dir/$plugin_name.$AppleVst3Extension"
    else
        post_error "$camo_name.$AppleVst3Extension is not available"
    fi
}

################################################################################
#                       GENERATE LV2 PLUGIN LINUX                              #
################################################################################

generate_plugin_lv2_linux() {
    local camo_name=$CamomileLV2
    local plugin_input_dir=$1
    local plugin_output_dir=$2
    local plugin_name=$(basename $1)

    # Check if the folder exists and get the type of the plugin
    if [ ! -d "$plugin_input_dir" ]; then
        post_error "$plugin_input_dir is not a directory"
        return
    fi

    # Get the dynamic libraries
    if [ -f "$ThisPath/$camo_name.$LinuxLV2Extension" ]; then
        if [ -d "$plugin_output_dir/$plugin_name.lv2" ]; then
            rm -rf "$plugin_output_dir/$plugin_name.lv2"
        fi

        mkdir "$plugin_output_dir/$plugin_name.lv2"
        cp -f "$ThisPath/$CamomileLV2.$LinuxLV2Extension" "$plugin_output_dir/$plugin_name.lv2/$plugin_name.$LinuxLV2Extension"
        cp -rf "$plugin_input_dir"/* "$plugin_output_dir/$plugin_name.lv2"

        LD_LIBRARY_PATH=$PWD "$ThisPath/lv2_file_generator" "$plugin_output_dir/$plugin_name.lv2/$plugin_name.$LinuxLV2Extension" $plugin_name
        mv -f "$PWD/manifest.ttl" "$plugin_output_dir/$plugin_name.lv2/manifest.ttl"
        if [ -f "$PWD/presets.ttl" ]; then
            mv -f "$PWD/presets.ttl" "$plugin_output_dir/$plugin_name.lv2/presets.ttl"
        fi
        mv -f "$PWD/$plugin_name.ttl" "$plugin_output_dir/$plugin_name.lv2/$plugin_name.ttl"
        post_log "$plugin_output_dir/$plugin_name.lv2"
    else
        post_error "$camo_name.$LinuxLV2Extension is not available"
    fi
}

################################################################################
#                       GENERATE VST PLUGIN LINUX                              #
################################################################################

generate_plugin_vst3_linux() {
    local camo_name
    local plugin_input_dir=$1
    local plugin_output_dir=$2
    local plugin_name=$(basename $1)

    # Check if the folder exists and get the type of the plugin
    if [ -d $plugin_input_dir ]; then
        local plugin_type=$(plugin_get_type $plugin_input_dir $plugin_name)
        if [ "$plugin_type" == "error" ]; then
            post_error "$plugin_input_dir does not contain description text file $plugin_name.txt"
            return
        elif [ "$plugin_type" == "instrument" ]; then
            camo_name=$CamomileInstrument
        elif [ "$plugin_type" == "effect" ]; then
            camo_name=$CamomileEffect
        else
            post_error "$plugin_type is not a valid"
            return
        fi
    else
        post_error "$plugin_input_dir is not a directory"
        return
    fi

    # Get the dynamic libraries
    if [ -d "$ThisPath/$camo_name.$LinuxVst3Extension" ]; then
      local plugin_bundle="$plugin_output_dir/$plugin_name.$LinuxVst3Extension"
        if [ -d $plugin_bundle ]; then
            rm -rf $plugin_bundle
        fi

        cp -rf "$ThisPath/$camo_name.$LinuxVst3Extension" $plugin_bundle
        cp -rf "$plugin_input_dir"/* "$plugin_bundle/Contents/x86_64-linux"
        mv -f "$plugin_bundle/Contents/x86_64-linux/$camo_name.so" "$plugin_bundle/Contents/x86_64-linux/$plugin_name.so"
        post_log "$plugin_output_dir/$plugin_name.$LinuxVst3Extension"
    else
        post_error "$camo_name.$LinuxVst3Extension is not available"
    fi
}

################################################################################
#                       GENERATE PLUGINS                                       #
################################################################################

generate_plugins() {
    if [ $machine == "Mac" ]; then
        if [[ "$vst3Only" == true ]]; then
            generate_plugin_vst3_mac $1 $2
        fi
        if [[ "$auOnly" == true ]]; then
            generate_plugin_au_mac $1 $2
        fi
        if [[ "$lv2Only" == true ]]; then
            generate_plugin_lv2_mac $1 $2
        fi
        if [[ "$vst3Only" != true ]] && [[ "$auOnly" != true ]] && [[ "$lv2Only" != true ]] ; then
            generate_plugin_vst3_mac $1 $2
            generate_plugin_au_mac $1 $2
            generate_plugin_lv2_mac $1 $2
        fi
    elif [ $machine == "Linux" ]; then
        if [[ "$vst3Only" == true ]]; then
            generate_plugin_vst3_linux "$1" "$2"
        fi
        if [[ "$lv2Only" == true ]]; then
            generate_plugin_lv2_linux "$1" "$2"
        fi
        if [[ "$vst3Only" != true ]] && [[ "$lv2Only" != true ]] ; then
            generate_plugin_vst3_linux "$1" "$2"
            generate_plugin_lv2_linux "$1" "$2"
        fi
    else
        post_error "$machine is not a supported"
    fi
}

################################################################################
#                       GENERATE ALL PLUGINS                                   #
################################################################################

generate_all_plugins() {
    local plugin_input_dir="$1"
    local plugin_output_dir="$2"

    if [ -d "$plugin_input_dir" ]; then
        for subfolder in $plugin_input_dir/*
        do
            if [ -d "$subfolder" ]; then
                local plugin_name=$(basename "$subfolder")
                if [ -f "$subfolder/$plugin_name.pd" ]; then
                    generate_plugins "$subfolder" "$plugin_output_dir"
                else
                    post_error "$subfolder does not contain a valid pd patch"
                fi
            else
                post_error "$subfolder is not a directory"
            fi
        done
    else
        post_error "$plugin_input_dir is not a directory"
        return
    fi
}

################################################################################
#                       CREATE OUTPUT DIRECTORY                                #
################################################################################

create_output_directory() {
    local output_dir="$1"
    if [ ! -d "$output_dir" ]; then
        mkdir "$output_dir"
    fi
}

################################################################################
#                                   HELP                                       #
################################################################################

display_help() {
    echo  -e "\033[1;30mCamomile Plugin Generator\033[0m"
    echo  -e "-f [pluginpath] - generate one plugin"
    echo  -e "-d [dirpath] - generate all the plugin in a directory"
    echo  -e "-o [outputpath] - set the ouput path"
    echo  -e "help - display help"
}

################################################################################
#                                   Main method                                #
################################################################################

if [ "$1" == "help" ]; then
    display_help
else
    setoutput="false"
    setpath="false"
    output_dir="./builds"
    FolderMode="true"
    FileMode="false"
    pluginpath="./Examples"

    for var in "$@"
    do
        if [[ "$setoutput" == "true" ]]; then
            output_dir="$var"
            setoutput=false
        elif [[ "$setpath" == "true" ]]; then
            pluginpath="$var"
            setpath=false
        elif [[ $var == "-d" ]]; then
            FileMode="false"
            FolderMode="true"
            setpath=true
            setoutput=false
        elif [[ $var == "-f" ]]; then
            FileMode="true"
            FolderMode="false"
            setpath=true
            setoutput=false
        elif [[ $var == "-o" ]]; then
            setoutput=true
            setpath=false
        elif [[ $var == "-au" ]]; then
            auOnly="true"
        elif [[ $var == "-lv2" ]]; then
            lv2Only="true"
        elif [[ $var == "-vst3" ]]; then
            vst3Only="true"
        else
            echo -e "\033[31m"$var" wrong arguments\033[0m"
        fi
    done

    create_output_directory $output_dir
    echo -e "Camomile - Plugin Generator"
    if [[ "$FolderMode" == true ]]; then
        generate_all_plugins "$pluginpath" "$output_dir"
    else
        generate_plugins "$pluginpath" "$output_dir"
    fi
fi
