/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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.
 */
package org.apache.commons.compress.harmony.pack200;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

/**
 * A PopulationCodec is a Codec that is well suited to encoding data that shows statistical or repetitive patterns, containing for example a few numbers which
 * are repeated a lot throughout the set, but not necessarily sequentially.
 */
public class PopulationCodec extends Codec {

    private final Codec favouredCodec;
    private Codec tokenCodec;
    private final Codec unfavouredCodec;
    private int l;
    private int[] favoured;

    public PopulationCodec(final Codec favouredCodec, final Codec tokenCodec, final Codec unvafouredCodec) {
        this.favouredCodec = favouredCodec;
        this.tokenCodec = tokenCodec;
        this.unfavouredCodec = unvafouredCodec;
    }

    public PopulationCodec(final Codec favouredCodec, final int l, final Codec unfavouredCodec) {
        if (l >= 256 || l <= 0) {
            throw new IllegalArgumentException("L must be between 1..255");
        }
        this.favouredCodec = favouredCodec;
        this.l = l;
        this.unfavouredCodec = unfavouredCodec;
    }

    @Override
    public int decode(final InputStream in) throws IOException, Pack200Exception {
        throw new Pack200Exception("Population encoding does not work unless the number of elements are known");
    }

    @Override
    public int decode(final InputStream in, final long last) throws IOException, Pack200Exception {
        throw new Pack200Exception("Population encoding does not work unless the number of elements are known");
    }

    @Override
    public int[] decodeInts(final int n, final InputStream in) throws IOException, Pack200Exception {
        lastBandLength = 0;
        favoured = new int[check(n, in)]; // there must be <= n values, but probably a lot
        // less
        int[] result;
        // read table of favorites first
        int smallest = Integer.MAX_VALUE, absoluteSmallest;
        int last = 0;
        int value = 0, absoluteValue;
        int k = -1;
        while (true) {
            value = favouredCodec.decode(in, last);
            if (k > -1 && (value == smallest || value == last)) {
                break;
            }
            favoured[++k] = value;
            absoluteSmallest = Math.abs(smallest);
            absoluteValue = Math.abs(value);
            if (absoluteSmallest > absoluteValue) {
                smallest = value;
            } else if (absoluteSmallest == absoluteValue) {
                // ensure that -X and +X -> +X
                smallest = absoluteSmallest;
            }
            last = value;
        }
        lastBandLength += k;
        // if tokenCodec needs to be derived from the T, L and K values
        if (tokenCodec == null) {
            if (k < 256) {
                tokenCodec = BYTE1;
            } else {
                // if k >= 256, b >= 2
                int b = 1;
                BHSDCodec codec;
                while (++b < 5) {
                    codec = new BHSDCodec(b, 256 - l, 0);
                    if (codec.encodes(k)) {
                        tokenCodec = codec;
                        break;
                    }
                }
                if (tokenCodec == null) {
                    throw new Pack200Exception("Cannot calculate token codec from " + k + " and " + l);
                }
            }
        }
        // read favorites
        lastBandLength += n;
        result = tokenCodec.decodeInts(n, in);
        // read unfavorites
        last = 0;
        for (int i = 0; i < n; i++) {
            final int index = result[i];
            if (index == 0) {
                lastBandLength++;
                result[i] = last = unfavouredCodec.decode(in, last);
            } else {
                result[i] = favoured[index - 1];
            }
        }
        return result;
    }

    @Override
    public byte[] encode(final int value) throws Pack200Exception {
        throw new Pack200Exception("Population encoding does not work unless the number of elements are known");
    }

    @Override
    public byte[] encode(final int value, final int last) throws Pack200Exception {
        throw new Pack200Exception("Population encoding does not work unless the number of elements are known");
    }

    public byte[] encode(final int[] favoured, final int[] tokens, final int[] unfavoured) throws Pack200Exception {
        final int[] favoured2 = Arrays.copyOf(favoured, favoured.length + 1);
        favoured2[favoured2.length - 1] = favoured[favoured.length - 1]; // repeat last value;
        final byte[] favouredEncoded = favouredCodec.encode(favoured2);
        final byte[] tokensEncoded = tokenCodec.encode(tokens);
        final byte[] unfavouredEncoded = unfavouredCodec.encode(unfavoured);
        final byte[] band = new byte[favouredEncoded.length + tokensEncoded.length + unfavouredEncoded.length];
        System.arraycopy(favouredEncoded, 0, band, 0, favouredEncoded.length);
        System.arraycopy(tokensEncoded, 0, band, favouredEncoded.length, tokensEncoded.length);
        System.arraycopy(unfavouredEncoded, 0, band, favouredEncoded.length + tokensEncoded.length, unfavouredEncoded.length);
        return band;
    }

    public int[] getFavoured() {
        return favoured;
    }

    public Codec getFavouredCodec() {
        return favouredCodec;
    }

    public Codec getTokenCodec() {
        return tokenCodec;
    }

    public Codec getUnfavouredCodec() {
        return unfavouredCodec;
    }
}
