// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.pqc.crypto.xmss;

import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.util.Integers;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.Map;
import java.io.Serializable;

public class BDSStateMap implements Serializable
{
    private static final long serialVersionUID = -3464451825208522308L;
    private final Map<Integer, BDS> bdsState;
    private transient long maxIndex;
    
    BDSStateMap(final long maxIndex) {
        this.bdsState = new TreeMap<Integer, BDS>();
        this.maxIndex = maxIndex;
    }
    
    BDSStateMap(final BDSStateMap bdsStateMap, final long maxIndex) {
        this.bdsState = new TreeMap<Integer, BDS>();
        for (final Integer n : bdsStateMap.bdsState.keySet()) {
            this.bdsState.put(n, new BDS(bdsStateMap.bdsState.get(n)));
        }
        this.maxIndex = maxIndex;
    }
    
    BDSStateMap(final XMSSMTParameters xmssmtParameters, final long n, final byte[] array, final byte[] array2) {
        this.bdsState = new TreeMap<Integer, BDS>();
        this.maxIndex = (1L << xmssmtParameters.getHeight()) - 1L;
        for (long n2 = 0L; n2 < n; ++n2) {
            this.updateState(xmssmtParameters, n2, array, array2);
        }
    }
    
    public long getMaxIndex() {
        return this.maxIndex;
    }
    
    void updateState(final XMSSMTParameters xmssmtParameters, final long n, final byte[] array, final byte[] array2) {
        final XMSSParameters xmssParameters = xmssmtParameters.getXMSSParameters();
        final int height = xmssParameters.getHeight();
        long n2 = XMSSUtil.getTreeIndex(n, height);
        final int leafIndex = XMSSUtil.getLeafIndex(n, height);
        final OTSHashAddress otsHashAddress = (OTSHashAddress)new OTSHashAddress.Builder().withTreeAddress(n2).withOTSAddress(leafIndex).build();
        if (leafIndex < (1 << height) - 1) {
            if (this.get(0) == null || leafIndex == 0) {
                this.put(0, new BDS(xmssParameters, array, array2, otsHashAddress));
            }
            this.update(0, array, array2, otsHashAddress);
        }
        for (int i = 1; i < xmssmtParameters.getLayers(); ++i) {
            final int leafIndex2 = XMSSUtil.getLeafIndex(n2, height);
            n2 = XMSSUtil.getTreeIndex(n2, height);
            final OTSHashAddress otsHashAddress2 = (OTSHashAddress)new OTSHashAddress.Builder().withLayerAddress(i).withTreeAddress(n2).withOTSAddress(leafIndex2).build();
            if (this.bdsState.get(i) == null || XMSSUtil.isNewBDSInitNeeded(n, height, i)) {
                this.bdsState.put(i, new BDS(xmssParameters, array, array2, otsHashAddress2));
            }
            if (leafIndex2 < (1 << height) - 1 && XMSSUtil.isNewAuthenticationPathNeeded(n, height, i)) {
                this.update(i, array, array2, otsHashAddress2);
            }
        }
    }
    
    public boolean isEmpty() {
        return this.bdsState.isEmpty();
    }
    
    BDS get(final int n) {
        return this.bdsState.get(Integers.valueOf(n));
    }
    
    BDS update(final int n, final byte[] array, final byte[] array2, final OTSHashAddress otsHashAddress) {
        return this.bdsState.put(Integers.valueOf(n), this.bdsState.get(Integers.valueOf(n)).getNextState(array, array2, otsHashAddress));
    }
    
    void put(final int n, final BDS bds) {
        this.bdsState.put(Integers.valueOf(n), bds);
    }
    
    public BDSStateMap withWOTSDigest(final ASN1ObjectIdentifier asn1ObjectIdentifier) {
        final BDSStateMap bdsStateMap = new BDSStateMap(this.maxIndex);
        for (final Integer n : this.bdsState.keySet()) {
            bdsStateMap.bdsState.put(n, this.bdsState.get(n).withWOTSDigest(asn1ObjectIdentifier));
        }
        return bdsStateMap;
    }
    
    private void readObject(final ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
        objectInputStream.defaultReadObject();
        if (objectInputStream.available() != 0) {
            this.maxIndex = objectInputStream.readLong();
        }
        else {
            this.maxIndex = 0L;
        }
    }
    
    private void writeObject(final ObjectOutputStream objectOutputStream) throws IOException {
        objectOutputStream.defaultWriteObject();
        objectOutputStream.writeLong(this.maxIndex);
    }
}
