/*
 *
 *  Copyright (C) 2021, 2024 Andrew Gegg
 *
 * 	This file is part of the Gardeners Notebook application
 *
 *  The Gardeners Notebook application is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 *
 */

 /*
    Change log
    3.2.1   Add functionality to remove duplicate keys.
 */

package uk.co.gardennotebook.mysql;

import uk.co.gardennotebook.spi.INotebookEntry;

import java.util.Arrays;
import java.util.List;

/**
 * Wraps up key collection for the *Listers
 *
 *	@author	Andy Gegg
 *	@version	3.2.1
 *	@since	3.0.0
 */
final  class DBKeyHandler<T extends INotebookEntry>
{

    private final String selectorName;

    private int[] idList = new int[10];
    private int idNext = 0;	// next free slot in list

    DBKeyHandler(String selectorName)
    {
        this.selectorName = selectorName;
    }

    /**
     * Append to the list of raw id's
     *
     * @param vals  a list of DB key values
     */
    void id(int ... vals)
    {
        if (idNext + vals.length >= idList.length)
        {
            idList = Arrays.copyOf(idList, idList.length+vals.length+10);
        }
        for (int val : vals)
        {
            idList[idNext++] = val;
        }
    }

    /**
     * Append to the list of DB id's
     *
     * @param vals  a list of items
     */
    void item(T... vals)
    {
        if (vals == null) return;
        if (vals.length == 0) return;
        int[] keys = new int[vals.length];
        int keyCount = 0;
        for (T item : vals)
        {
            if (item == null) continue;
            Integer ky = item.getKey();
            if (ky == null) continue;
            keys[keyCount++] = ky;
        }
        if (keyCount == 0) return;
        keys = Arrays.copyOf(keys, keyCount);	// trim array to actual size - should be a null-op
        id(keys);
    }

    /**
     * Append to the list of DB id's
     *
     * @param vals  a list of items
     */
    void item(List<T> vals)
    {
        if (vals == null) return;
        if (vals.isEmpty()) return;
        int[] keys = new int[vals.size()];
        int keyCount = 0;
        for (T item : vals)
        {
            if (item == null) continue;
            Integer ky = item.getKey();
            if (ky == null) continue;
            keys[keyCount++] = ky;
        }
        if (keyCount == 0) return;
        keys = Arrays.copyOf(keys, keyCount);	// trim array to actual size - should be a null-op
        id(keys);
    }

    /**
     * Is this selector used?
     *
     * @return  true if used
     */
    boolean isUsed()
    {
        return idNext > 0;
    }

    /**
     * Generate the SQL clause for this selector
     *
     * @param alias  the name of the selector field's alias in the DB record
     *
     * @return  a SQL clause
     */
    String getSQLClause(String alias)
    {
        String clause = " " + alias + "." + selectorName;
        if (idNext > 1) {
            clause += " in (";
            for(int ix = 0; ix < idNext; ix++) { clause += idList[ix] + ", "; }
            clause = clause.substring(0, clause.length() - 2);
            clause += ")";
        }
        else
            clause += " = " + idList[0];

        return clause;
    }

    /**
     * Get the list of ids.  Some Listers need this (e.g. PlantSpeciesLister) if they optimise to fetch from the cache
     */
    int[] getIds()
    {
        return Arrays.copyOf(idList, idNext);
    }

    void removeDuplicates()
    {
        int[] copy = new int[idList.length];
        Arrays.sort(idList);
        int hold = -1;  //  the most recent key in idList
        int ix = 0; //  the next slot to use in copy
        for (int key : idList)
        {
            if (key == hold) continue;
            copy[ix++] = key;
            hold = key;
        }
    }

    /**
     * Clear down for subsequent use
     */
    void clear()
    {
        idList = new int[10];
        idNext = 0;
    }

}
