#!/bin/bash
# Copyright 2016 Mir Calculate. http://www.calculate-linux.org
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

PATH=/lib/rc/bin:$PATH

PROG=cl-theme
TEXTDOMAIN=cl_theme
CL_THEME_VERSION=0.2.0_beta1
DESCRIPTION=$"The program for themes creating"
LOCAL_TEMPLATES_DIR=/var/calculate/templates
THEME_TEMPLATES=${LOCAL_TEMPLATES_DIR}/theme
DEBUG_LOG=${DEBUG_LOG:-/var/log/calculate/${PROG}.log}
INIENV=/etc/calculate/ini.env
INIPARAM=( main theme )
touch $DEBUG_LOG &>/dev/null || DEBUG_LOG=/dev/null
# права на файл шаблона
# template file privileges
CHMOD=0644
XRESOLUTIONS=(
    1024x576  1280x1024  1360x768   1440x900   1680x1050  2048x1152  800x480
    1024x600  1280x720   1366x768   1600x1200  1680x945   2560x1440  800x600
    1024x768  1280x768   1368x768   1600x768   1920x1080  2560x1600
    1200x800  1280x800   1400x1050  1600x900   1920x1200  640x480
)

FBRESOLUTIONS=( ${XRESOLUTIONS[@]} )
GRUBRESOLUTION=1920x1440
GFXBOOTRESOLUTION=640x480

CREATE_TEMPLATES=${CREATE_TEMPLATES-1}
CUSTOM_THEMES=1

# прервать скрипт в случае ошибки любой из команд
# break the script execution in case of a command error
set -e

: >$DEBUG_LOG

# вывод короткой справки
# show the short help message
usage() {
    echo $"Usage: $PROG [OPTION]

Version: $CL_THEME_VERSION

${DESCRIPTION}
"
    echo -n "  --help                     "
    echo $"display this help and exit"
}

# вывод полной справки
# show the long help message
long_usage() {
    echo $"Usage: $PROG [OPTION]"
    echo $"Version: $CL_THEME_VERSION"
    echo
    echo $"${DESCRIPTION}"
    echo
    echo -n "  --help                     "
    echo $"display this help and exit"
    echo -n "  -L,--live                  "
    echo $"create live boot menu theme"
    echo -n "  -B,--boot                  "
    echo $"create grub boot menu theme"
    echo -n "  -b,--booting               "
    echo $"create boot theme"
    echo -n "  -s,--shutdown              "
    echo $"create shutdown theme"
    echo -n "  -w,--wallpaper             "
    echo $"create wallpaper themes"
    echo -n "  -l,--login                 "
    echo $"create theme for login screen"
    echo -n "  -S,--session               "
    echo $"create login and logout theme"
}

# подготовить параметры командной строки
# prepare the commmand line parameters
rearrange_params() {
    set +e
    TEMP=$(unset POSIXLY_CORRECT; getopt \
        -o "hw:l:S:b:s:B:L:" \
        --long help \
        --long wallpaper: \
        --long login: \
        --long session: \
        --long booting: \
        --long shutdown: \
        --long boot: \
        -- "$@" 2>&1)
    if (( $? != 0 )); then
        echo "$TEMP" | sed "s/getopt: /$PROG: /;\$d"
        exit 1
    fi
    set -e
}

# выполнить параметры командной строки
# apply the command line parameters
do_args() {
    while :; do
        case $1 in
        -h|--help)
            long_usage
            exit 0
            ;;
        -w|--wallpaper)
            WALLPAPERS_SOURCE="$2"
            shift
            ;;
        -l|--login)
            LOGIN_SOURCE="$2"
            shift
            ;;
        -S|--session)
            SESSION_SOURCE="$2"
            shift
            ;;
        -b|--booting)
            BOOTING_SOURCE="$2"
            shift
            ;;
        -s|--shutdown)
            SHUTDOWN_SOURCE="$2"
            shift
            ;;
        -L|--live)
            GFXBOOT_SOURCE="$2"
            shift
            ;;
        -B|--boot)
            GRUB_SOURCE="$2"
            shift
            ;;
        --) shift;break;;
        *) usage;
           eerror $"Unknown option: $1"
           ;;
       esac
       shift
    done
    if [[ -n $1 ]]
    then
        usage;
        eerror $"Unknown argument: $1"
    fi
}

# получить значение переменной calculate
# get the value of variable 'calculate'
variable_value()
{
    local varname=$1
    /usr/libexec/calculate/cl-variable --value $varname
}

# получить значение из ini файла (значение возвращается без пробелов)
# get the value from ini file (value was returned without space chars)
ini_value() {
    local section=$1
    local key=$2
    [[ -f $INIENV ]] || return 0
    set -o pipefail
    awk -F ' *= *' -v section="[$section]" -v k="$key" \
    '$0==section { f=1; next}
    /\[/{f=0; next}
    f && $1==k { print $2}' $INIENV 2>>$DEBUG_LOG  | tr -d " "
    set +o pipefail
}

write_ini_value() {
    local outfile=$(tempfile -p ini. -s .cl-theme 2>>$DEBUG_LOG)
    chmod 644 $outfile 2>>$DEBUG_LOG || eerror $"Failed to prepare to ini.env" || exit 1
    [[ -f $INIENV ]] || touch $INIENV 2>>$DEBUG_LOG
    awk -v section="[$1]" -v k="$2" -v v="$3" '
        BEGIN {add = "\n" section "\n" k " = " v "\n"}
        # пропускаем обработку если уже добавили параметр
        !add {print;next}
        # если нужная секция (будем добавлять в секцию(ins=1))
        $0==section {ins=1;print;add= k " = " v "\n"; next}
        # если нашли нужный параметр
        ins && $1==k {printf add;add="";ins=0;next}
        # если новая секция
        ins && $0 ~ /\[/ {print add "\n" $0;add="";ins=0;next}
        # пропускаем пустые строки если мы будем добавлять в эту секцию
        !ins || $0 !~ /^$/ {print}
        END {printf add}' $INIENV >$outfile 2>>$DEBUG_LOG || eerror $"Failed to prepare to ini.env" || exit 1
    mv $outfile $INIENV &>>$DEBUG_LOG || eerror $"Failed to write to ini.env" || exit 1
}

generate_uuid() {
    local uuid=$(uuidgen | awk -F- '{print $1}')
    write_ini_value ${INIPARAM[@]} $uuid && echo $uuid
}

#####################
# Подготовка шаблонов
#####################

prepare_templates() {
    local uuid
    uuid=$(ini_value ${INIPARAM[@]}) || eerror $"Failed to read to ini.env" || exit 1

    [[ -n $uuid ]] || uuid=$(generate_uuid)
    [[ -n $uuid ]] || eerror $"Failed to generate UUID" || exit 1
    if ! [[ -d $THEME_TEMPLATES ]]
    then
        mkdir -p $THEME_TEMPLATES
        cat >$THEME_TEMPLATES/.calculate_directory <<EOF
# Calculate append=skip env=install ac_install_merge==on||ac_install_disk==on
EOF
    fi
    THEMEUUID=${THEME_TEMPLATES}/$uuid
    if ! [[ -d $THEME_TEMPLATES ]]
    then
        mkdir -p $THEMEUUID
        cat >$THEME_TEMPLATES/.calculate_directory <<EOF
# Calculate append=skip ini(${INIPARAM[0]}.${INIPARAM[1]})==#-cl_file_pass-#
EOF
    fi

    # create migrate templates
    livecd=$(variable_value main.os_root_type)
    if [[ $livecd == livecd ]]
    then
        mkdir -p $THEME_TEMPLATES/migrate
        cat >$THEME_TEMPLATES/migrate/.calculate_directory <<EOF
# Calculate ac_install_disk==on&&ini(${INIPARAM[0]}.${INIPARAM[1]})!= link=#-cl_install_path_from-#/var/calculate/templates/theme/#-ini(${INIPARAM[0]}.${INIPARAM[1]})-# path=/var/calculate/templates/theme name=#-ini(${INIPARAM[0]}.${INIPARAM[1]})-#
EOF
    fi
}

create_category_template() {
    local category_dn=${1}/${2}
    if ! [[ -d $category_dn ]]
    then
        mkdir -p $category_dn &>>$DEBUG_LOG || eerror $"Failed to create $category_dn" || exit 1
        cat >$category_dn/.calculate_directory <<EOF
# Calculate append=skip
EOF
    fi
}

create_package_template() {
    local pn_dn=${1}/${2}/${3}
    local pathparam=$(dirname $4)
    local nameparam=$(basename $4)
    if ! [[ -d $pn_dn ]]
    then
        mkdir -p $pn_dn &>>$DEBUG_LOG || eerror $"Failed to create $pn_dn" || exit 1
        cat >$pn_dn/.calculate_directory <<EOF
# Calculate path=$pathparam name=$nameparam mergepkg()!=
EOF
    fi
}

########################
# Image working
# Работа с изображениями
########################
image_resolution() {
    local image=$1
    identify -format "%[w] %[h]" "$image"
}

convert_image() {
    local source_image=$1
    local res=$2
    local target_image=$3

    convert -quality 95 $source_image -resize "$res^" -gravity center -crop "$res+0+0" ${CONVERT_APPEND} $target_image &>>${DEBUG_LOG}
}

filter_resolutions() {
    local source_image=$1
    local data=( $(image_resolution $source_image) )
    local source_width=${data[0]}
    local source_height=${data[1]}
    shift
    for res in $@
    do
        data=( ${res/x/ } )
        local width=${data[0]}
        local height=${data[1]}
        [[ $source_width -lt $width ]] || [[ $source_height -lt $height ]] && continue
        echo $res
    done
}

###############################
# Общий алгоритм создания обоев
###############################
create_wallpaperlike_images() {
    local source_image=$1
    local dest=$2
    local theme_name=$3
    local theme_name_meta=$4

    local filtered_resolutions
    PREVIEW_RES=400x250
    local theme_path=${dest}/${theme_name}
    local images=$theme_path/contents/images

    mkdir -p $images &>>$DEBUG_LOG || return 1

    filtered_resolutions=$(filter_resolutions $source_image ${XRESOLUTIONS[@]})

    [[ -n "${filtered_resolutions}" ]] || eerror $"Source image is too small" || return 1

    local leastone
    for res in ${filtered_resolutions}
    do
        ebegin $"Creating image ${res}"
        convert_image $source_image $res $images/${res}.jpg 
        res=$?
        eend $res
        [[ $res -eq 0 ]] && leastone=1
    done
    [[ -n $leastone ]] || return 1

    ebegin $"Creating preview"
    convert_image $source_image $PREVIEW_RES $theme_path/contents/screenshot.jpg
    res=$?
    eend $res
    [[ $res -eq 0 ]] || return 1

    local subname=$(variable_value os_linux_subname)
    local themename="$(variable_value os_linux_name)${subname:+ ${subname}} DM"

    cat 2>>$DEBUG_LOG >$theme_path/metadata.desktop <<EOF
[Desktop Entry]
Name=${theme_name_meta}
EOF
}

###################################
# Общий алгоритм создания fb splash
###################################

create_splashlike_images() {
    local source_image=$1
    local dest=$2
    local theme_name=$3
    local prefix=$4

    local filtered_resolutions
    local theme_path=${dest}/${theme_name}
    local images=$theme_path/images

    mkdir -p $images &>>$DEBUG_LOG || return 1

    filtered_resolutions=$(filter_resolutions $source_image ${FBRESOLUTIONS[@]})

    [[ -n "${filtered_resolutions}" ]] || eerror $"Source image is too small" || return 1

    local leastone
    for res in ${filtered_resolutions}
    do
        ebegin $"Creating image ${res}"
        convert_image $source_image $res $images/${prefix}${res}.jpg 
        res=$?
        eend $res
        [[ $res -eq 0 ]] && leastone=1
    done
    [[ -n $leastone ]] && return 0 || return 1
}

create_silent_templates() {
    local dest=$1
    local data width height
    for image in $dest/images/*
    do
        data=( $(image_resolution $image) )
        width=${data[0]}
        height=${data[1]}
        cat >$dest/${width}x${height}.cfg <<EOF
# Calculate comment=#

# background image
silentpic=$(realpath --relative-to=${dest} $image)

# progress bar for silent mode
box silent inter 0 $(( $height - 1)) 0 ${height} #ffffff
box silent 0 $(( $height - 1)) $width ${height} #ffffff
EOF
    done
}

#######################
# Тема загрузки системы
# System boot splash
#######################
create_booting_images() {
    rm -rf $1/${BOOTING_THEME:-custom}
    create_splashlike_images $BOOTING_SOURCE $1 ${BOOTING_THEME:-custom} silent-
}

create_booting_cfgs() {
    create_silent_templates $1/${BOOTING_THEME:-custom}
}

create_booting_templates() {
    create_category_template ${THEMEUUID} media-gfx
    create_package_template ${THEMEUUID} media-gfx splash-themes-calculate /etc/splash || return 1
    BOOTING_INSTALL_PATH="${THEMEUUID}/media-gfx/splash-themes-calculate"
}

create_booting() {
    [[ -n $CREATE_TEMPLATES ]] && create_booting_templates
    create_booting_images ${BOOTING_INSTALL_PATH:-/etc/splash} &&
    create_booting_cfgs ${BOOTING_INSTALL_PATH:-/etc/splash}
}

#########################
# Тема выключения системы
# System shutdown splash
#########################
create_shutdown_images() {
    rm -rf $1/${SHUTDOWN_THEME:-custom_shutdown}
    create_splashlike_images $SHUTDOWN_SOURCE $1 ${SHUTDOWN_THEME-custom_shutdown} silent-
}

create_shutdown_cfgs() {
    create_silent_templates $1/${SHUTDOWN_THEME-custom_shutdown}
}

create_shutdown_templates() {
    create_category_template ${THEMEUUID} media-gfx
    create_package_template ${THEMEUUID} media-gfx splash-themes-calculate /etc/splash || return 1
    SHUTDOWN_INSTALL_PATH="${THEMEUUID}/media-gfx/splash-themes-calculate"
}

create_shutdown() {
    [[ -n $CREATE_TEMPLATES ]] && create_shutdown_templates
    create_shutdown_images ${SHUTDOWN_INSTALL_PATH:-/etc/splash} &&
    create_shutdown_cfgs ${SHUTDOWN_INSTALL_PATH:-/etc/splash}
}

############
# Wallpapers
# Обои
############
create_wallpapers_images() {
    local subname=$(variable_value os_linux_subname)
    local themename="$(variable_value os_linux_name)${subname:+ ${subname}}"
    rm -rf $1/${WALLPAPERS_THEME:-custom}
    create_wallpaperlike_images $WALLPAPERS_SOURCE $1 ${WALLPAPERS_THEME-custom} ${WALLPAPERS_THEME_NAME:-${themename}}
}

create_wallpapers_templates() {
    create_category_template ${THEMEUUID} media-gfx
    create_package_template ${THEMEUUID} media-gfx calculate-wallpapers /usr/share/wallpapers || return 1
    WALLPAPERS_INSTALL_PATH="${THEMEUUID}/media-gfx/calculate-wallpapers"
}

create_wallpapers() {
    [[ -n $CREATE_TEMPLATES ]] && create_wallpapers_templates
    create_wallpapers_images ${WALLPAPERS_INSTALL_PATH:-/usr/share/wallpapers}
}

######################
# Экран логина
# Login screen
######################
create_login_images() {
    local subname=$(variable_value os_linux_subname)
    local themename="$(variable_value os_linux_name)${subname:+ ${subname}} DM"
    rm -rf $1/${LOGIN_THEME:-custom-dm}
    create_wallpaperlike_images $LOGIN_SOURCE $1 ${LOGIN_THEME-custom-dm} ${LOGIN_THEME_NAME:-${themename}}
}

create_login_templates() {
    create_category_template ${THEMEUUID} media-gfx
    create_package_template ${THEMEUUID} media-gfx dm-themes-calculate /usr/share/wallpapers || return 1
    LOGIN_INSTALL_PATH="${THEMEUUID}/media-gfx/dm-themes-calculate"
}

create_login() {
    [[ -n $CREATE_TEMPLATES ]] && create_session_templates
    create_session_images ${LOGIN_INSTALL_PATH:-/usr/share/wallpapers}
}

######################
# Вход в сессию
# Session login
######################
create_session_images() {
    local subname=$(variable_value os_linux_subname)
    local themename="$(variable_value os_linux_name)${subname:+ ${subname}} Splash"
    rm -rf $1/${SESSION_THEME:-custom-splash}
    create_wallpaperlike_images $SESSION_SOURCE $1 ${SESSION_THEME:-custom-splash} ${SESSION_THEME_NAME:-${themename}}
}

create_session_templates() {
    create_category_template ${THEMEUUID} media-gfx
    create_package_template ${THEMEUUID} media-gfx dm-themes-calculate /usr/share/wallpapers || return 1
    SESSION_INSTALL_PATH="${THEMEUUID}/media-gfx/dm-themes-calculate"
}

create_session() {
    [[ -n $CREATE_TEMPLATES ]] && create_session_templates
    create_session_images ${SESSION_INSTALL_PATH:-/usr/share/wallpapers}
}

#######################
# Gfxboot
#######################
create_gfxboot_images() {
    local img=$1/${GFXBOOT_THEME:-back-custom}.jpg
    rm $img &>>${DEBUG_LOG}
    convert_image $GFXBOOT_SOURCE $GFXBOOTRESOLUTION $img

}

create_gfxboot_templates() {
    create_category_template ${THEMEUUID} media-gfx
    create_package_template ${THEMEUUID} media-gfx gfxboot-themes-calculate /usr/share/themes/gfxboot-themes-calculate || return 1
    GFXBOOT_INSTALL_PATH="${THEMEUUID}/media-gfx/gfxboot-themes-calculate"
}

create_gfxboot() {
    [[ -n $CREATE_TEMPLATES ]] && create_gfxboot_templates
    create_gfxboot_images ${GFXBOOT_INSTALL_PATH:-/usr/share/themes/gfxboot-themes-calculate}
}

#######################
# Grub theme
#######################
create_grub_images() {
    local img=$1/${GRUB_THEME:-grub-custom}.png
    rm $img &>>${DEBUG_LOG}
    filtered_resolutions=$(filter_resolutions $GRUB_SOURCE $GRUBRESOLUTION)
    [[ -n "${filtered_resolutions}" ]] || eerror $"Source image is too small" || return 1
    convert_image $GRUB_SOURCE $GRUBRESOLUTION $img

}

create_grub_templates() {
    create_category_template ${THEMEUUID} media-gfx
    create_package_template ${THEMEUUID} media-gfx grub-splashes-calculate /boot/grub || return 1
    GRUB_INSTALL_PATH="${THEMEUUID}/media-gfx/grub-splashes-calculate"
}

create_grub() {
    [[ -n $CREATE_TEMPLATES ]] && create_grub_templates
    create_grub_images ${GRUB_INSTALL_PATH:-/boot/grub}
}

######################
# Обработать параметры
# Process the options
######################
rearrange_params "$@"
eval set -- "$TEMP"
do_args "$@"

[[ -n $CREATE_TEMPLATES ]] && prepare_templates

if [[ -n $WALLPAPERS_SOURCE ]]
then
    einfo $"Creating wallpapers theme"
    create_wallpapers || eerror $"Failed to create wallpapers" || exit 1
fi

if [[ -n $LOGIN_SOURCE ]]
then
    einfo $"Creating login screen theme"
    create_login || eerror $"Failed to create login screen theme" || exit 1
fi

if [[ -n $SESSION_SOURCE ]]
then
    einfo $"Creating session login theme"
    create_session || eerror $"Failed to create session login theme" || exit 1
fi

if [[ -n $BOOTING_SOURCE ]]
then
    einfo $"Creating booting theme"
    create_booting || eerror $"Failed to create booting theme" || exit 1
fi

if [[ -n $SHUTDOWN_SOURCE ]]
then
    einfo $"Creating shutdown theme"
    create_shutdown || eerror $"Failed to create shutdown theme" || exit 1
fi

if [[ -n $GFXBOOT_SOURCE ]]
then
    einfo $"Creating live boot menu theme"
    create_gfxboot || eerror $"Failed to create live boot menu theme" || exit 1
fi

if [[ -n $GRUB_SOURCE ]]
then
    einfo $"Creating grub boot menu theme"
    create_grub || eerror $"Failed to create grub boot menu theme" || exit 1
fi

[[ -n $WALLPAPERS_SOURCE ]] && cl-core-setup --pkg-name calculate-wallpapers
[[ -n $LOGIN_SOURCE ]] || [[ -n $SESSION_SOURCE ]] && cl-core-setup --pkg-name dm-themes-calculate
[[ -n $SHUTDOWN_SOURCE ]] || [[ -n $BOOTING_SOURCE ]] && cl-core-setup --pkg-name splash-themes-calculate
[[ -n $GFXBOOT_SOURCE ]] && cl-core-setup --pkg-name gfxboot-themes-calculate
[[ -n $GRUB_SOURCE ]] && cl-core-setup --pkg-name grub-splashes-calculate

einfo $"All done!"
