<template>
    <div v-if="isProcessing" class="progress">
        <progress>Разливаем...</progress>
    </div>
    <div v-else>
        <h2 v-if="result.state == 'error'" class="error">
            {{ result.message }}
        </h2>
        <div v-for="jam in jams" :key="jam.id">
            <h3>
                Варенье: {{ jam.id }}, всего сварено: {{ jam.vol }} мл,
                <span v-if="jam.restVol > 0" class="error"
                    >осталось не розлито: {{ jam.restVol }} мл</span
                >
                <span v-else>розлито полностью</span>
            </h3>
            <ul>
                <li v-for="pot in jam.pots" :key="pot.id">
                    <span
                        >Банка <b>{{ pot.id }}</b> ({{ pot.vol }} мл)</span
                    >
                    &mdash;
                    <span> залито {{ pot.jamVol }} мл</span>
                    &mdash;
                    <span v-if="pot.isFull"> полная</span>
                    <b v-else class="error">
                        недолив {{ pot.vol - pot.jamVol }} мл</b
                    >
                </li>
            </ul>
        </div>
        <div v-if="emptyPots.length > 0">
            <hr>
            <h4>Остались пустые банки:</h4>
            <ul>
                <li v-for="pot in emptyPots" :key="pot.id">
                    <b>{{ pot.id }}</b> ({{ pot.vol }} мл)
                </li>
            </ul>
        </div>
    </div>
</template>

<script>
import { _ } from "vue-underscore";
export default {
    props: ["propPots", "propJams"],
    data() {
        return {
            isProcessing: false,
            pots: [],
            jams: [],
            result: { state: "initial" },
        };
    },
    mounted: function () {
        this.isProcessing = true;

        this.pots = _.map(this.propPots, _.clone);
        this.jams = _.map(this.propJams, _.clone);

        this.result = fillPots(this.pots, this.jams);

        // console.log("result", this.result);
        // console.log("jams", this.jams);

        this.isProcessing = false;
    },
    computed: {
        emptyPots: function () {
            return this.pots.filter((p) => p.jamVol === 0);
        },
    },
};

function fillPots(pots, jams) {
    prepare(pots, jams);

    // Сперва попытаемся разлить варенья по банкам, заполняя их по максимуму
    // Приоритет отдаем самым большим банкам, чтобы не лазать в погреб лишний раз

    let isDone = false;
    let isFoundSolution;
    do {
        isFoundSolution = false;
        for (const jam of jams) {
            for (const pot of pots) {
                if (!pot.isFilled && pot.vol <= jam.restVol) {
                    pot.jamId = jam.id;
                    pot.jamVol = Math.min(pot.vol, jam.restVol);
                    pot.isFilled = true;
                    pot.isFull = true;
                    jam.restVol -= pot.vol;
                    jam.pots.push(pot);
                    isFoundSolution = true;
                    break;
                }
            }
        }
    } while (!isDone && isFoundSolution);

    // А теперь разливаем остатки по самым маленьким из оставшихся банок

    isDone = true;
    for (const jam of jams) {
        if (jam.restVol > 0) {
            for (let i = pots.length - 1; i > 0; i--) {
                if (!pots[i].isFilled && pots[i].vol >= jam.restVol) {
                    pots[i].jamId = jam.id;
                    pots[i].jamVol = jam.restVol;
                    pots[i].isFilled = true;
                    pots[i].isFull = pots[i].vol === jam.restVol;
                    jam.restVol = 0;
                    jam.pots.push(pots[i]);
                    break;
                }
            }
            if (jam.restVol !== 0) {
                isDone = false;
            }
        }
    }

    if (!isDone) {
        return {
            state: "error",
            message: "Не удалось разлить варенья",
        };
    }

    return { state: "success" };

    function prepare(pots, jams) {
        pots.sort(sortByVolDesc);
        jams.sort(sortByVolDesc);

        for (const pot of pots) {
            pot.isFilled = false;
            pot.isFull = false;
            pot.jamId = null;
            pot.jamVol = 0;
        }

        for (const jam of jams) {
            jam.restVol = jam.vol;
            jam.pots = [];
        }

        function sortByVolDesc(a, b) {
            if (a.vol > b.vol) {
                return -1;
            } else if (a.vol < b.vol) {
                return 1;
            }
            return 0;
        }
    }
}
</script>

<style lang="scss" scoped>
.progress {
    height: 100%;
    display: flex;
    align-items: center;
    progress {
        width: 100%;
    }
}
.error {
    color: orangered;
}
</style>
