#!/usr/bin/bash

# import imageshell functions
# https://stackoverflow.com/q/192292
MY_DIR=/usr/share/pokeshell
source $MY_DIR/imageshell/imageshell.sh

# Function that prints out the help text
_help() {
    echo "pokeshell: Show Pokemon sprites in the terminal"

    echo ""
    echo "Usage: pokeshell [OPTION] POKEMON..."
    printf "  %-20s\t%-54s\n" \
        "-b, --big" "Display big sprites (default)" \
        "-a, --animation" "Display animated sprites" \
        "-s, --small" "Display small sprites" \
        "-n, --show-name" "Show names of displayed Pokemon" \
        "-r, --remove-cache" "Remove cache directory" \
        "-h, --help" "Print this help" \

    echo ""
    echo "Shiny: prepend \"✨/s(hiny):\" or \"ns/not-shiny:\""
    echo "               or \"all:\" to POKEMON"
    echo "       prepending nothing uses the base shiny rate of 1/4096"
    echo "       prepending \"all:\" specifies shiny and not shiny"

    echo ""

    echo "Gender: append \"+♂/m(ale)\" or \"+♀/f(emale)\""
    echo "               or \"+all\" to POKEMON"
    echo "        appending nothing uses the gender ratio of pokemon"
    echo "        appending \"+all\" specifies both male and female"

    echo ""

    echo "Random: use \"random{,GEN,...}\" for POKEMON"
    echo "can add comma separated list for random pokemon from specified gens"
    echo "note: specifying a gender for random is a suggestion as"
    echo "random pokemon may have gender restrictions"
    echo ""

    echo "Examples: pokeshell pikachu"
    echo "          pokeshell s:pikachu+♂ ns:pikachu+♀"
    echo "          pokeshell all:pikachu+all"
    echo "          pokeshell -s random s:pikachu-gmax"
    echo "          pokeshell -b charizard-mega-x+male ✨:ho-oh moltres-galar"
    echo "          pokeshell -a -n all:bulbasaur pikachu+all"
    echo "          pokeshell -n random,1,3+f s:random,4,1"
    echo "          pokeshell bulbasaur BULBASAUR 1 フシギダネ fushigidane"
    echo "          pokeshell s:이상해씨 妙蛙種子+♀ Bulbizarre Bisasam"
    echo "          pokeshell nidoran-f+f nidoran-m type-null farfetchd sirfetchd"
}

# Handling command line arguments (ghetto getopt)
case "$#" in
    0)
        # display help if no arguments are given
        _help
        exit
        ;;
    *)
        use_small=0
        use_ani=0
        show_name=0
        cache=1
        cache_dir="$HOME/.cache/pokeshell"
        first_pokemon_idx=1
        last_flag_idx=0
        true_gender=0

        # First flag
        if [ "$1" == '-r' ] || [ "$1" == '--remove-cache' ]; then
            rm -r -v "$cache_dir" | grep -v "removed '"
            exit
        elif [ "$1" == '-s' ] || [ "$1" == '--small' ]; then
            use_small=1
            first_pokemon_idx=$((first_pokemon_idx+1))
            last_flag_idx=$((last_flag_idx+1))
        elif [ "$1" == '-a' ] || [ "$1" == '--animation' ]; then
            use_ani=1
            first_pokemon_idx=$((first_pokemon_idx+1))
            last_flag_idx=$((last_flag_idx+1))
        elif [ "$1" == '-b' ] || [ "$1" == '--big' ]; then
            first_pokemon_idx=$((first_pokemon_idx+1))
            last_flag_idx=$((last_flag_idx+1))
        elif [ "$1" == '-h' ] || [ "$1" == '--help' ]; then
            _help
            exit
        elif [ "$1" == '-n' ] || [ "$1" == '--show-name' ]; then
            show_name=1
            first_pokemon_idx=$((first_pokemon_idx+1))
            last_flag_idx=$((last_flag_idx+1))
        fi

        # Second flag
        # minor fixme: check if last_flag_idx has been incremented
        if [ "$2" == '-n' ] || [ "$2" == '--show-name' ]; then
            show_name=1
            first_pokemon_idx=$((first_pokemon_idx+1))
            last_flag_idx=$((last_flag_idx+1))
        fi

        # Check if any pokemon listed
        # minor fixme: ||/or the below two if statements
        if [ $# == 1 ] && [ $last_flag_idx == 1 ]; then
            _help
            echo ""
            echo "You forgot to mention any Pokemon! See help."
            exit
        fi

        if [ $# == 2 ] && [ $last_flag_idx == 2 ]; then
            _help
            echo ""
            echo "You forgot to mention any Pokemon! See help."
            exit
        fi

        # Parse description
        images=()
        descriptions=( "${@:$first_pokemon_idx}" )
        while [[ ${#descriptions[@]} != 0 ]]; do

            # Pop the first desc from descriptions as we are about to parse it
            desc="${descriptions[0]}"
            descriptions=("${descriptions[@]:1}")

            # Parse for shiny
            IFS=':' read -ra desc_arr <<< "$desc"
            if [ ${#desc_arr[@]} == 1 ]; then
                pokemon=${desc_arr[0]}
                shiny_str=''
            else
                shiny_str=${desc_arr[0]}
                pokemon=${desc_arr[1]}
            fi

            # Parse for gender
            IFS='+' read -ra desc_arr <<< "$pokemon"
            if [ ${#desc_arr[@]} == 1 ]; then
                pokemon=${desc_arr[0]}
                gender_str=''
            else
                pokemon=${desc_arr[0]}
                gender_str=${desc_arr[1]}
            fi

            # Parse for random
            # Delimit pokemon on comma to see if we are using random gens
            is_random=0
            IFS=',' read -ra pokemon_random_arr <<< "$pokemon"
            pokemon=${pokemon_random_arr[0]}

            if [ "$pokemon" = 'random' ]; then
                is_random=1
                gen_ids=(1 152 251 387 494 650 722 810 898)
                gen_start=0
                gen_end=8

                # Delimit pokemon on comma to see if we are using random gens
                if [ ${#pokemon_random_arr[@]} != 1 ]; then
                    use_random_gen=1
                    for (( _idx=1; _idx<${#pokemon_random_arr[@]}; _idx++ )); do
                        gens+=("${pokemon_random_arr[_idx]}")
                    done

                    # Pick random gen
                    random_gen=$(shuf -e "${gens[@]}" -n 1)
                    gen_end=${random_gen}
                    gen_start=$((gen_end-1))
                fi

                # Choose random pokemon id
                pokemon_id=$(shuf -i "${gen_ids[gen_start]}"-"${gen_ids[gen_end]}" -n 1)
                pokemon=$(curl -s \
                    "https://pokeapi.co/api/v2/pokemon/$pokemon_id" | \
                    jq -r '.species.name')

                # TODO
                # Check to see if the pokemon has forms and if so random off that
                # upstream issue, pokeapi should list forms on pokemon_species
                # POST

                # But wait there is more
                # If random let's figure out which form to use
                # TODO
            fi

            # Get canonical name from input name
            # Lowercase
            pokemon=$(echo "$pokemon" | tr '[:upper:]' '[:lower:]')

            # Check if pokemon is a known identifier (id, canonical name, localized name)
            input_pokemon="$pokemon"
            pokemon=$(jq -r '."'"$pokemon"'"' "$MY_DIR/pokemon_identifiers.json")
            # If identifier not found in our list, fall back to each backend's list
            if [ "$pokemon" == "null" ]; then
                pokemon="$input_pokemon"
            fi

            # meowstic is weird in pokeapi (upstream issue?)
            # male shiny is actually female shiny?
            if [ "$pokemon" == 'meowstic' ]; then
                pokemon=meowstic-male
            fi

            gender_rate=4
            if [ $true_gender == 1 ]; then
                # Check if pokemon exists! If not use unown-? lol
                http_code=$(curl -s -o /dev/null -I -w "%{http_code}" \
                    "https://pokeapi.co/api/v2/pokemon/$pokemon")
                if [ "$http_code" == '404' ]; then
                    # Could be a pokemon form
                    # Note forms are generally inconsistant in terms of if default
                    # pokemon species displays a form or doesn't.
                    # See shellos vs unown for example
                    is_form=1
                    http_code=$(curl -s -o /dev/null -I -w "%{http_code}" \
                        "https://pokeapi.co/api/v2/pokemon-form/$pokemon")
                    if [ "$http_code" == '404' ]; then
                        # Okay now it probably doesn't exist
                        echo "$pokemon is unown ?"
                        pokemon='unown-question'
                    fi

                    # TODO giratina is weird as well between pokeapi and pokesprite
                    # and probably other forms as well
                fi

                if [ "$is_form" == '1' ]; then
                    pokemon_species=$(curl -s https://pokeapi.co/api/v2/pokemon-form/$pokemon | \
                        jq -r '.pokemon.name')
                else
                    pokemon_species=$(curl -s https://pokeapi.co/api/v2/pokemon/$pokemon | \
                        jq -r '.species.name')
                fi

                # Ensure proper gender is used (if a pokemon cannot be male or cannot
                # be female that is enforced)
                gender_rate=$(curl -s "https://pokeapi.co/api/v2/pokemon-species/$pokemon_species" | \
                    jq -r '.gender_rate')
            fi

            # meowstic is weird in pokeapi (upstream issue?)
            # convert meowstic-male back to meowstic for the other backends
            if [ $pokemon == 'meowstic-male' ]; then
                pokemon=meowstic
                gender_rate=4
            fi

            if [ -z "$shiny_str" ]; then
                # Random shiny chance
                shiny_str='not-shiny'
                shiny_rate=4096
                shiny_chance=$(shuf -i 1-"$shiny_rate" -n 1)
                if [ "$shiny_chance" = "$shiny_rate" ]; then
                    shiny_str='shiny'
                fi
            fi

            if [ $shiny_str = 'shiny' ] || [ $shiny_str = 's' ] || [ $shiny_str = '✨' ]; then
                _type=shiny
            elif [ $shiny_str = 'not-shiny' ] || [ $shiny_str = 'ns' ]; then
                _type=not-shiny
            elif [ $shiny_str = 'all' ]; then
                # After expanding all shiny options for this pokemon, continue to next iteration
                not_shiny_desc="not-shiny:${pokemon}+${gender_str}"
                shiny_desc="shiny:${pokemon}+${gender_str}"
                descriptions=("${not_shiny_desc}" "${shiny_desc}" "${descriptions[@]}")
                continue
            else
                _help
                echo ""
                echo "Incorrect shiny specifier! See help."
                exit
            fi


            if [ -z "$gender_str" ]; then

                # Random gender chance based on pokemon gender ratio
                if [ "$gender_rate" = '-1' ]; then
                    gender_str='genderless'
                else
                    gender_div=8
                    gender_chance=$(shuf -i 1-"$gender_div" -n 1)
                    if [[ $gender_chance -le $gender_rate ]]; then
                        gender_str='female'
                    else
                        gender_str='male'
                    fi
                fi
            fi

            if [ $gender_str = 'male' ] || [ $gender_str = 'm' ] || [ $gender_str = '♂' ]; then
                if [ "$gender_rate" = '8' ]; then
                    if [ $is_random = 0 ]; then
                        echo "$pokemon must be female!"
                        echo ""
                        exit
                    else
                        gender=female
                    fi
                elif [ "$gender_rate" = '-1' ]; then
                    if [ $is_random = 0 ]; then
                        echo "$pokemon has no gender!"
                        echo ""
                        exit
                    else
                        gender=male
                    fi
                else
                    gender=male
                fi
            elif [ $gender_str = 'female' ] || [ $gender_str = 'f' ] || [ $gender_str = '♀' ]; then
                if [ $gender_rate = '0' ]; then
                    if [ $is_random = 0 ]; then
                        echo "$pokemon must be male!"
                        echo ""
                        exit
                    else
                        gender=male
                    fi
                elif [ $gender_rate = '-1' ]; then
                    if [ $is_random = 0 ]; then
                        echo "$pokemon has no gender!"
                        echo ""
                        exit
                    else
                        # use default gender of male
                        gender=male
                    fi
                else
                    gender=female
                fi
            elif [ $gender_str = 'genderless' ]; then
                if [ $gender_rate != '-1' ]; then
                    echo "$pokemon_species cannot be genderless!"
                    echo ""
                    exit
                else
                    # use default gender of male
                    gender=male
                fi
            elif [ $gender_str = 'all' ]; then
                # After expanding all gender options for this pokemon, continue to next iteration
                if [ $gender_rate = '0' ]; then
                    desc="${shiny_str}:${pokemon}+male"
                    descriptions=("${desc}" "${descriptions[@]}")
                elif [ "$gender_rate" = '8' ]; then
                    desc="${shiny_str}:${pokemon}+female"
                    descriptions=("${desc}" "${descriptions[@]}")
                elif [ "$gender_rate" = '-1' ]; then
                    desc="${shiny_str}:${pokemon}"
                    descriptions=("${desc}" "${descriptions[@]}")
                else
                    desc_male="${shiny_str}:${pokemon}+male"
                    desc_female="${shiny_str}:${pokemon}+female"
                    descriptions=("${desc_male}" "${desc_female}" "${descriptions[@]}")
                fi
                continue
            else
                _help
                echo ""
                echo "Incorrect gender specifier! See help."
                exit
            fi

            # Create full pokemon description for filename/caching
            cache_dir="$HOME/.cache/pokeshell"
            mkdir -p "$cache_dir"
            desc_full="${_type}:$pokemon+${gender}"
            if [ "$show_name" == 1 ]; then
                # TODO: show name in various languages, potentially with a
                # -n=ja, --show-name=es, --show-name=japanese, etc.
                # TODO: for gender use ♂/♀
                echo "$desc_full"
            fi

            # Check if image is cached
            is_cached=0
            if [ $use_small == 1 ]; then
                possible_cached_pokemon="$cache_dir/$desc_full-small.png"
            elif [ $use_ani == 1 ]; then
                possible_cached_pokemon="$cache_dir/$desc_full.gif"
            else
                possible_cached_pokemon="$cache_dir/$desc_full-big.png"
            fi

            if [ -f "$possible_cached_pokemon" ]; then
                is_cached=1
                image=${possible_cached_pokemon}
            fi

            # curl images
            if [ $use_small == 1 ] && [ "$is_cached" == 0 ]; then
                # default type of small sprites is "regular"
                if [ $_type = 'not-shiny' ]; then
                    _type=regular
                fi
                if [ $gender = 'male' ]; then
                    gender=''
                fi

                if [ $pokemon = 'nidoran-f' ]; then
                    gender=''
                fi

                # Only limited number is exclusively female,
                # thus need to do a check to see if female exists
                # if not revert to male (i.e. gender='')
                http_code=$(curl -s -o /dev/null -I -w "%{http_code}" \
                    "https://raw.githubusercontent.com/msikma/pokesprite/master/pokemon-gen8/$_type/$gender/$pokemon.png")
                if [ "$http_code" == '404' ]; then
                    gender=''
                fi

                image="$cache_dir/$desc_full-small.png"
                curl -sL \
                    "https://raw.githubusercontent.com/msikma/pokesprite/master/pokemon-gen8/$_type/$gender/$pokemon.png" \
                    -o "$image"
            elif [ $use_ani == 1 ] && [ "$is_cached" == 0 ]; then
                # default type of ani sprites is "normal"
                if [ $_type = 'not-shiny' ]; then
                    _type=normal
                fi

                if [ "$gender" = 'female' ] && [ "$pokemon" != 'nidoran-f' ]; then
                    gender='-f'
                else
                    gender=''
                fi

                # Only limited number is exclusively female,
                # thus need to do a check to see if female exists
                # if not revert to male (i.e. gender='')
                http_code=$(curl -s -o /dev/null -I -w "%{http_code}" \
                    "https://projectpokemon.org/images/$_type-sprite/$pokemon$gender.gif")
                if [ "$http_code" == '404' ]; then
                    gender=''
                fi

                # ani sprites unique naming search and replace
                # nidoran-f/m => nidoran_f/m
                pokemon=${pokemon/nidoran-f/nidoran_f}
                pokemon=${pokemon/nidoran-m/nidoran_m}
                # type-null => typenull
                pokemon=${pokemon/type-null/typenull}
                # mega-{x/y} => mega{x/y}
                pokemon=${pokemon/mega-/mega}
                # gmax => gigantamax
                pokemon=${pokemon/gmax/gigantamax}

                image="$cache_dir/$desc_full.gif"
                curl -sL \
                    "https://projectpokemon.org/images/$_type-sprite/$pokemon$gender.gif" \
                    -o "$image"
            elif [ ${is_cached} == 0 ]; then
                # default type of big sprites is "default"
                if [ "$_type" = 'not-shiny' ] && [ "$gender" != 'female' ]; then
                    _desc=default
                elif [ "$_type" = 'not-shiny' ] && [ "$gender" == 'female' ]; then
                    _desc=female
                    _fallback=default
                elif [ "$_type" = 'shiny' ] && [ "$gender" != 'female' ]; then
                    _desc=shiny
                else
                    _desc=shiny_female
                    _fallback=shiny
                fi

                # meowstic is weird in pokeapi (upstream issue?)
                # male shiny is actually female shiny?
                if [ $pokemon == 'meowstic' ]; then
                    pokemon=meowstic-male
                fi

                json_field=".sprites.front_${_desc}"

                url=$(curl -s "https://pokeapi.co/api/v2/pokemon-form/$pokemon" | \
                    jq -r $json_field)

                if [ "$url" == 'null' ]; then
                    url=$(curl -s "https://pokeapi.co/api/v2/pokemon/$pokemon" | \
                        jq -r $json_field)
                    if [ "$url" == '' ]; then
                        url="null"
                    fi
                fi

                # Only limited number is exclusively female,
                # thus need to do a check to see if female exists
                # if not revert to male (i.e. gender='')
                # note for female only pokemon, pokeapi uses male classifier
                if [ "$url" == 'null' ]; then
                    _desc=$_fallback
                    json_field=".sprites.front_${_desc}"
                    url=$(curl -s "https://pokeapi.co/api/v2/pokemon-form/$pokemon" | \
                        jq -r $json_field)
                    if [ "$url" == 'null' ]; then
                        url=$(curl -s "https://pokeapi.co/api/v2/pokemon/$pokemon" | \
                            jq -r $json_field)
                    fi
                fi
                image="$cache_dir/$desc_full-big.png"
                curl -sL "$url" -o "$image"
            fi
            images+=("${image}")
        done
        ;;
esac

scale=0
trim=1
pixel_perfect=1
imgshl_display images $use_ani $scale $trim $pixel_perfect $cache "$cache_dir"
