#!/usr/bin/env sh
#
# ----------------------------------------------------------------------------
#
# Copyright 2019 IBM Corporation
#
# 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.
#
# ----------------------------------------------------------------------------
#

set -eu

usage() {
    echo "Usage: $(basename "$0") db_file score_min_goal max_functions min_size [-functions]"
    echo ""
    echo "    This helper script finds the parameters to find"
    echo "    the right settings that maximize the coverage "
    echo "    within the specified constraints."
    echo ""
    echo "    db_file: ChopStiX database file"
    echo "    score_min_goal: Minimum coverage"
    echo "    max_functions: Maximum number of functions"
    echo "    min_size: Minimum size of functions (in instructions)"
    echo "    -functions: execute the command and list the selected function names only"
    echo ""
}

score_min_goal=50
score_max_func=20
score_min_size=50

if [ $# -lt 4 ]; then
    usage
    exit 1
fi

if [ $# -gt 5 ]; then
    usage
    exit 1
fi

db="$1"
if [ ! -f "$db" ]; then
    echo "$db not found!"
    exit 1
fi

db="$(mktemp)"
tmp="$(mktemp)"
tmp2="$(mktemp)"

cleanup() {
    rm -f "$tmp" "$tmp2" "$db"
}
trap cleanup EXIT

score_min_goal="$2"
score_max_func="$3"
score_min_size="$4"

function=0
if [ $# -eq 5 ]; then
    if [ "$5" != "-functions" ]; then
        usage
        rm -f "$tmp" "$tmp2" "$db"
        exit 1
    else
        function=1
    fi
fi

trap 'rm -f $db $tmp $tmp2' EXIT

cp -f "$1" "$db"

coverant=0
for min in 5 1 0.1; do

    set +e
    chop list functions -data "$db" -min "$min" -limit "$score_max_func" -summary > "$tmp" 2> /dev/null
    set -e

    if [ "$(wc -l "$tmp" | cut -d ' ' -f 1)" -eq 0 ]; then
        funct=0
        cover=0
    else
        funct=$(grep Results < "$tmp" | cut -d' ' -f 2)
        cover=$(grep Score < "$tmp" | cut -d' ' -f 2)
    fi

    if [ "$(echo "$cover" | cut -d '.' -f 1)" -lt "$score_min_goal" ]; then
        continue
    fi

    for size in 1000 $(seq 1 50 1001) 0; do

        if [ "$size" -lt "$score_min_size" ]; then
            continue
        fi

        set +e
        chop list functions -data "$db" -min "$min" -minsize "$size" -limit "$score_max_func" -summary > "$tmp" 2> /dev/null
        set -e

        if [ "$(wc -l "$tmp" | cut -d ' ' -f 1)" -eq 0 ]; then
            funct=0
            cover=0
        else
            funct=$(grep Results < "$tmp" | cut -d' ' -f 2)
            cover=$(grep Score < "$tmp" | cut -d' ' -f 2)
        fi
        if [ "$funct" -le "$score_max_func" ]; then
            if [ "$(echo "$cover" | cut -d '.' -f 1)" -ge "$score_min_goal" ]; then
                if [ "$cover" != "$coverant" ]; then
                    echo "$min $size $funct $cover" >> "$tmp2"
                    coverant="$cover"
                fi
            fi
        fi
    done;
done;
rm -f "$tmp"

if [ "$(wc -l < "$tmp2")" -eq 0 ]; then
    echo "No valid configurations found. Relax constraints."
    rm -f "$tmp" "$tmp2" "$db"
    exit 1
fi

winner="$(sort -b -n -r -k 4,4 < "$tmp2" | head -n 1)"

if [ $function -eq 0 ]; then
    echo "--------------------------------------"
    echo "Valid configuration"
    echo "--------------------------------------"
    echo "MINSCORE MINSIZE FUNCTIONS COVERAGE" > "$tmp"
    sort -b -n -r -k 4,4 < "$tmp2" >> "$tmp"
    column -t < "$tmp"
    echo "--------------------------------------"
    echo "Best score: $(echo "$winner" | cut -d' ' -f 4)"
    echo "--------------------------------------"

    echo "Command to execute"
    echo "--------------------------------------"
    echo "chop list functions -data $db -min $(echo "$winner" | cut -d' ' -f 1) -minsize $(echo "$winner" | cut -d' ' -f 2) -limit $(echo "$winner" | cut -d' ' -f 3)"
else
    chop list functions -data "$db" -min "$(echo "$winner" | cut -d' ' -f 1)" -minsize "$(echo "$winner" | cut -d' ' -f 2)" -limit "$(echo "$winner" | cut -d' ' -f 3)" | cut -f 2 | grep -v "^NAME$"
fi

rm -f "$tmp" "$tmp2" "$db"
exit 0
