#!/bin/sh
PATH=/usr/local/bin:/usr/local/sbin:~/bin:/usr/bin:/bin:/usr/sbin:/sbin

readonly SCRIPT=$(basename "$0")
readonly VERSION='1.1.1'
RESOLUTIONS=(1920x1200 1920x1080 1024x768 1280x720 1366x768 UHD)
MONITOR="0" # 0 means all monitors
PLIST_FILE="$HOME/Library/LaunchAgents/com.bing-wallpaper-daily-mac-multimonitor"
AUTO_UPDATE_NAME="default"
ARGS=$@

usage() {
cat <<EOF
Usage:
  $SCRIPT [options]
  $SCRIPT -h | --help
  $SCRIPT --version

Options:
  enable-auto-update             Enable automatic update of wallpapers every day
                                 the picture if the filename already exists.
  disable-auto-update            Disable automatic update of wallpapers every day
                                 the picture if the filename already exists.
  info                           Show description of current wallpaper.
  --auto-update-name <name>      Name of your auto update when enabling/disabling
                                 Using custom name enables setting multiple automatic update configurations.
                                 Eg. Set on monitor 1 todays wallpaper and on monitor 2 wallpaper from yesterday                                                           
  -f --force                     Force download of picture. This will overwrite
                                 the picture if the filename already exists.
  -s --ssl                       Communicate with bing.com over SSL.
  -q --quiet                     Do not display log messages.
  -c --country <coutry-tag>      Specify market country/region eg. en-US, cs-CZ
                                 Pictures may be different for markets on some days.
                                 See full list of countries on https://learn.microsoft.com/en-us/previous-versions/bing/search/dd251064(v=msdn.10)
  -d --day <number>              Day for which you want to get the picture.
                                 0 is current day, 1 is yesterday etc.
                                 Default is 0.
  -n --filename <file name>      The name of the downloaded picture. Defaults to
                                 the upstream name.
  -p --picturedir <picture dir>  The full path to the picture download dir.
                                 Will be created if it does not exist.
                                 [default: $HOME/Pictures/bing-wallpapers/]
  -r --resolution <resolution>   The resolution of the image to retrieve.
                                 Supported resolutions: ${RESOLUTIONS[*]}
  --resolutions <resolutions>    The resolutions of the image try to retrieve.
                                 eg.: --resolutions "1920x1200 1920x1080 UHD"
  -m --monitor <num>             Set wallpaper only on certain monitor (1,2,3...)
  --all-desktops-experimental    Set wallpaper on all desktops
                                 Fixing osascript bug when wallpaper is not set for Desktop 2.
                                 Known issue: Minimized apps are removed from Dock.
                                 If something goes wrong delete Library/Application Support/Dock/desktoppicture.db
                                 and restart your Mac.                    
  -h --help                      Show this screen.
  --version                      Show version.
EOF
}

create_plist_in_users_agents_folder() {
    local SCRIPT_PATH=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )/$(basename "${BASH_SOURCE:-$0}")
    local REST_ARGS=$(echo "$ARGS" | sed -e "s/enable-auto-update//")
    
    if [ $RUN_USING_NPX ]; then
        local COMMANDS="<string>source ~/.bashrc && npx --yes bing-wallpaper-daily-mac-multimonitor@latest $REST_ARGS</string>"
    else
        local COMMANDS="<string>$SCRIPT_PATH $REST_ARGS</string>"
    fi

    cat > $PLIST_FILE <<- EOM
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.bing-wallpaper-daily-mac-multimonitor.plist</string>
    <key>OnDemand</key>
    <true/>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/sh</string>
		<string>-c</string>
        $COMMANDS
    </array>
    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    </dict>
     <key>StandardErrorPath</key>
    <string>/tmp/bing-wallpaper-daily-mac-multimonitor-plist.err</string>
    <key>StandardOutPath</key>
    <string>/tmp/bing-wallpaper-daily-mac-multimonitor-plist.out</string>
    <key>StartInterval</key>
    <integer>1800</integer>
	<key>RunAtLoad</key>
	<true/>
</dict>
</plist>
EOM

launchctl unload -w $PLIST_FILE 2>/dev/null
launchctl load -w $PLIST_FILE 
}

remove_plist_in_users_agents_folder() {
    launchctl unload -w "$PLIST_FILE" 2>/dev/null
    rm "$PLIST_FILE"
}

show_info_text() {
    # Parse HPImageArchive API and acquire picture BASE URL
COPYRIGHT=$(cat "$PICTURE_DIR/info.xml" | \
    grep -Eo "<copyright>.*<\/copyright>")
COPYRIGHT=$(echo "$COPYRIGHT" | sed -e "s/<copyright>//")
COPYRIGHT=$(echo "$COPYRIGHT" | sed -e "s/<\/copyright>//")
echo $COPYRIGHT
}

print_message() {
    if [ ! "$QUIET" ]; then
        printf "%s\n" "$(date): ${1}"
    fi
}

download_image_curl () {
    local RES=$1
    FILEURLWITHRES="${FILEURL}_${RES}.jpg"
    echo $FILEURLWITHRES
    FILENAME=${FILEURLWITHRES/\/th\?id=/}
    FILENAME_LOCAL="${AUTO_UPDATE_NAME}-${FILENAME}"
    FILEWHOLEURL="$PROTO://bing.com/$FILEURLWITHRES"

    if [ $FORCE ] || [ ! -f "$PICTURE_DIR/$FILENAME_LOCAL" ]; then
        find $PICTURE_DIR -type f -iname $AUTO_UPDATE_NAME-\*.jpg -delete
        print_message "Downloading: $FILENAME..."
        curl --fail -Lo "$PICTURE_DIR/$FILENAME_LOCAL" "$FILEWHOLEURL"
        curl --fail -Lo "$PICTURE_DIR/info.xml" "$BING_HP_IMAGE_ARCHIVE_URL"
        if [ "$?" == "0" ]; then
            FILEPATH="$PICTURE_DIR/$FILENAME_LOCAL"
            return
        fi

        FILEPATH=""
        return
    else
        print_message "Skipping download: $FILENAME_LOCAL..."
        FILEPATH="$PICTURE_DIR/$FILENAME_LOCAL"
        DOWNLOAD_SKIPPED=true
        return
    fi
}

set_wallpaper () {
    local FILEPATH=$1
    local MONITOR=$2

    if [ "$MONITOR" -ge 1 ] 2>/dev/null; then
    print_message "Setting wallpaper for monitor: $MONITOR"
    osascript - << EOF
        set tlst to {}
        tell application "System Events"
            set tlst to a reference to every desktop
            set picture of item $MONITOR of tlst to "$FILEPATH"
        end tell
EOF
    else
        osascript -e 'tell application "System Events" to tell every desktop to set picture to "'$FILEPATH'"'
    fi
}

set_wallpaper_experimental () {
    local db_file="Library/Application Support/Dock/desktoppicture.db"
    local db_path="$HOME/$db_file"

    # Put the image path in the database
    local sql="insert into data values(\"$FILEPATH\"); "
    sqlite3 "$db_path" "$sql"

    # Get the index of the new entry
    local sql="select max(rowid) from data;"
    local new_entry=$(sqlite3 "$db_path" "$sql")
    local new_entry=$(echo $new_entry|tr -d '\n')

    # Get all picture ids (monitor/space pairs)
    local sql="select rowid from pictures;"
    local pictures_string=$(sqlite3 "$db_path" "$sql")

    local IFS=$'\n'
    local pictures=($pictures_string)

    # Clear all existing preferences
    local sql="select max(rowid) from data; delete from preferences; "

    for pic in "${pictures[@]}"
    do
        if [ "$pic" ]; then
            local sql+="insert into preferences (key, data_id, picture_id) "
            local sql+="values(1, $new_entry, $pic); "
        fi
    done

    sqlite3 "$db_path" "$sql"

    killall "Dock"
}

# Defaults
PICTURE_DIR="$HOME/Pictures/bing-wallpapers/"

# Option parsing
while [[ $# -gt 0 ]]; do
    key="$1"

    case $key in
        enable-auto-update)
            ENABLE_AUTOMATIC_UPDATE=true
            ;;
        disable-auto-update)
            DISABLE_AUTOMATIC_UPDATE=true
            ;;
        info)
            INFO=true
            ;;
        --auto-update-name)
            AUTO_UPDATE_NAME="$2"
            shift
            ;;
        -r|--resolution)
            RESOLUTION="$2"
            shift
            ;;
        -p|--picturedir)
            PICTURE_DIR="$2"
            shift
            ;;
        -c|--country)
            COUNTRY="$2"
            shift
            ;;
        -d|--day)
            DAY="$2"
            shift
            ;;
        -n|--filename)
            FILENAME="$2"
            shift
            ;;
        -m|--monitor)
            MONITOR="$2"
            shift
            ;;
        -f|--force)
            FORCE=true
            ;;
        -s|--ssl)
            SSL=true
            ;;
        -q|--quiet)
            QUIET=true
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        --resolutions)
            RESOLUTIONS="$2"
            shift
            ;;
        --all-desktops-experimental)
            EXPERIMENTAL=true
            ;;
        --version)
            printf "%s\n" $VERSION
            exit 0
            ;;
        *)
            (>&2 printf "Unknown parameter: %s\n" "$1")
            usage
            exit 1
            ;;
    esac
    shift
done

# Set options
[ $QUIET ] && CURL_QUIET='-s'
[ $SSL ]   && PROTO='https'   || PROTO='http'
[ $DAY ]   && IDX=$DAY   || IDX='0'
BING_HP_IMAGE_ARCHIVE_URL="https://www.bing.com/HPImageArchive.aspx?format=xml&idx=${IDX}&n=1"
[ $COUNTRY ]   && BING_HP_IMAGE_ARCHIVE_URL="${BING_HP_IMAGE_ARCHIVE_URL}&mkt=${COUNTRY}"
PLIST_FILE="${PLIST_FILE}-${AUTO_UPDATE_NAME}.plist"

PARENT_COMMAND=$(ps -o comm= $PPID)
if [[ "$PARENT_COMMAND" == *"npm exec"* ]]; then
  RUN_USING_NPX=true
fi

if [ "$ENABLE_AUTOMATIC_UPDATE" ]; then
# enable update
create_plist_in_users_agents_folder
echo "Automatic wallpaper update enabled"
exit 1
fi

if [ "$DISABLE_AUTOMATIC_UPDATE" ]; then
# disable update
remove_plist_in_users_agents_folder
echo "Automatic wallpaper update disabled"
exit 1
fi

if [ "$INFO" ]; then
show_info_text
exit 1
fi

# Create picture directory if it doesn't already exist
mkdir -p "${PICTURE_DIR}"

# Parse HPImageArchive API and acquire picture BASE URL
FILEURL=( $(curl -sL $BING_HP_IMAGE_ARCHIVE_URL | \
    grep -Eo "<urlBase>.*?</urlBase>") )
FILEURL=$(echo "$FILEURL" | sed -e "s/<urlBase>//")
FILEURL=$(echo "$FILEURL" | sed -e "s/<\/urlBase>//")

if [ $RESOLUTION ]; then
    download_image_curl $RESOLUTION
    if [ "$FILEPATH" ]; then
        if [ "$EXPERIMENTAL" ]; then
            if [ ! "$DOWNLOAD_SKIPPED" ]; then
                set_wallpaper_experimental $FILEPATH
            fi
        else
            set_wallpaper $FILEPATH $MONITOR
        fi
    fi
    exit 1
fi

for RESOLUTION in "${RESOLUTIONS[@]}"
    do
        download_image_curl $RESOLUTION
        if [ "$FILEPATH" ]; then
            if [ "$EXPERIMENTAL" ]; then
                if [ ! "$DOWNLOAD_SKIPPED" ]; then
                    set_wallpaper_experimental $
                fi
            else
                set_wallpaper $FILEPATH $MONITOR
            fi
            exit 1
        fi
    done
