/*_############################################################################
  _## 
  _##  SNMP4J-AgentX - DefaultAgentXSharedMOTable.java  
  _## 
  _##  Copyright (C) 2005-2026  Frank Fock (SNMP4J.org)
  _##  
  _##  This program is free software; you can redistribute it and/or modify
  _##  it under the terms of the GNU General Public License version 2 as 
  _##  published by the Free Software Foundation.
  _##
  _##  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, write to the Free Software
  _##  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
  _##  MA  02110-1301  USA
  _##  
  _##########################################################################*/

package org.snmp4j.agent.agentx.subagent;

import org.snmp4j.agent.mo.*;
import org.snmp4j.smi.OID;

/**
 * The {@code DefaultAgentXSharedMOTable} class is a default implementation for a shared table. It supports dynamic
 * (while AgentX session is up) row creation and deletion.
 *
 * @author Frank Fock
 * @version 2.1
 */
@SuppressWarnings("rawtypes")
public class DefaultAgentXSharedMOTable
        <R extends MOTableRow, C extends MOColumn, M extends MOTableModel<R>>
        extends DefaultMOTable<R, C, M>
        implements AgentXSharedMutableMOTable<R, C, M> {
    private AgentXSharedMOTableSupport<R,?> sharedTableSupport;
    private byte overrideIndexAllocationMode = 0;
    private byte overridePriority = 0;


    /**
     * Creates a new shared table with the specified "Entry" OID, INDEX, columns, and a
     * {@link DefaultMOMutableTableModel} as table model.
     *
     * @param oid
     *         the OID of the SNMP table's Entry object. If the table is ifTable (1.3.6.1.2.1.2.2) then the OID to
     *         provide is  1.3.6.1.2.1.2.2.1 which is the ifEntry OID. By SMI rule, you can simply append ".1" to the
     *         table OID.
     * @param indexDef
     *         the index definition of the table based on the INDEX clause of the table MIB definition.
     * @param columns
     *         the column definitions which may also include non-accessible columns.
     */
    public DefaultAgentXSharedMOTable(OID oid, MOTableIndex indexDef, C[] columns) {
        super(oid, indexDef, columns);
    }

    /**
     * Creates a new shared table with the specified "Entry" OID, INDEX, columns, and a
     * {@link DefaultMOMutableTableModel} as table model.
     *
     * @param oid
     *         the OID of the SNMP table's Entry object. If the table is ifTable (1.3.6.1.2.1.2.2) then the OID to
     *         provide is  1.3.6.1.2.1.2.2.1 which is the ifEntry OID. By SMI rule, you can simply append ".1" to the
     *         table OID.
     * @param indexDef
     *         the index definition of the table based on the INDEX clause of the table MIB definition.
     * @param columns
     *         the column definitions which may also include non-accessible columns.
     * @param model
     *         the table model to be used by the shared table.
     */
    public DefaultAgentXSharedMOTable(OID oid, MOTableIndex indexDef, C[] columns, M model) {
        super(oid, indexDef, columns, model);
    }

    public AgentXSharedMOTableSupport<R,?> getAgentXSharedMOTableSupport() {
        return sharedTableSupport;
    }

    public void setAgentXSharedMOTableSupport(AgentXSharedMOTableSupport<R,?> sharedTableSupport) {
        if (this.sharedTableSupport != null) {
            removeMOTableRowListener(this.sharedTableSupport);
        }
        this.sharedTableSupport = sharedTableSupport;
        addMOTableRowListener(this.sharedTableSupport);
    }

    /**
     * Gets the index allocation mode that overrides the allocation mode inherited from the shared table support for
     * index allocation operations for this shared table.
     * @return
     *    0 if there is no overriding and the overridden mode otherwise.
     */
    public byte getOverrideIndexAllocationMode() {
        return overrideIndexAllocationMode;
    }

    /**
     * Gets the index priority that overrides the priority inherited from the shared table support for
     * index allocation operations for this shared table.
     * @return
     *    0 if there is no overriding and the overridden priority otherwise.
     */
    public byte getOverridePriority() {
        return overridePriority;
    }

    /**
     * Sets the index allocation mode that overrides the allocation mode inherited from the shared table support for
     * index allocation operations for this shared table.
     *
     * @param overrideIndexAllocationMode
     *         an index allocation mode as defined by {@link AgentXSharedMOTableSupport} or zero to use the default
     *         priority.
     */
    public void setOverrideIndexAllocationMode(byte overrideIndexAllocationMode) {
        this.overrideIndexAllocationMode = overrideIndexAllocationMode;
    }

    /**
     * Sets the registration priority that overrides the priority inherited from the shared table support object (if not
     * equal zero).
     *
     * @param overridePriority
     *         a value between 1 and 255 (-1 respectively - its a byte) or zero which indicates that the default
     *         priority should be used.
     */
    public void setOverridePriority(byte overridePriority) {
        this.overridePriority = overridePriority;
    }

    /**
     * Change the row index of a row in this shared table and trigger index allocation updates indirectly by
     * firing a new {@link MOTableRowEvent#UPDATED} event.
     * @param oldIndex
     *         the old index of the row to change.
     * @param newIndex
     *         the new index of the row.
     * @return
     *    {@code true} if the row index has been changed, {@code false} otherwise.
     */
    public boolean changeRowIndex(OID oldIndex, OID newIndex) {
        if (model instanceof MOMutableTableModel) {
            @SuppressWarnings("unchecked")
            MOMutableTableModel<R> mutableModel = (MOMutableTableModel<R>) model;
            R r = mutableModel.removeRow(oldIndex);
            if (r == null) {
                return false;
            }
            r.getIndex().setValue(newIndex.getValue());
            R existingRow = mutableModel.addRow(r);
            if (existingRow != null) {
                mutableModel.removeRow(newIndex);
                r.getIndex().setValue(oldIndex.getValue());
                mutableModel.addRow(r);
                mutableModel.addRow(existingRow);
                return false;
            }
            fireRowChanged(new MOTableRowEvent<R>(this, this, r, MOTableRowEvent.UPDATED, false));
            return true;
        }
        return false;
    }

}
