/*
 * 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.openjpa.lib.rop;

import java.util.Comparator;


/**
 * A result object provider that merges multiple result object provider
 * delegates. Support exists for maintaining ordering of the internally held
 * results, provided that each of the individual results is itself ordered.
 *
 * @author Abe White
 * @author Marc Prud'hommeaux
 */
public class MergedResultObjectProvider implements ResultObjectProvider {

    private static final byte UNOPENED = 0;
    private static final byte OPENED = 1;
    private static final byte VALUE = 2;
    private static final byte DONE = 3;

    private final ResultObjectProvider[] _rops;
    private final Comparator _comp;
    private final byte[] _status;
    private Object[] _values;
    private Object[] _orderValues;
    private Object _cur = null;
    private int _size = -1;

    /**
     * Constructor. Provide delegates.
     */
    public MergedResultObjectProvider(ResultObjectProvider[] rops) {
        this(rops, null);
    }

    /**
     * Constructor. Provide delegates and optional comparator.
     */
    public MergedResultObjectProvider(ResultObjectProvider[] rops,
        Comparator comp) {
        _rops = rops;
        _comp = comp;
        _status = new byte[rops.length];
        _values = (comp == null) ? null : new Object[rops.length];
        _orderValues = (comp == null) ? null : new Object[rops.length];
    }

    @Override
    public boolean supportsRandomAccess() {
        return false;
    }

    @Override
    public void open() throws Exception {
        // if we have a comparator, then open all; else open first
        int len = (_comp != null) ? _rops.length : 1;
        for (int i = 0; i < len; i++) {
            _rops[i].open();
            _status[i] = OPENED;
        }
    }

    @Override
    public boolean absolute(int pos) throws Exception {
        throw new UnsupportedOperationException();
    }

    @Override
    public int size() throws Exception {
        if (_size != -1)
            return _size;

        // have to open all to get sizes
        for (int i = 0; i < _status.length; i++) {
            if (_status[i] == UNOPENED) {
                _rops[i].open();
                _status[i] = OPENED;
            }
        }

        int total = 0;
        int size;
        for (int i = 0; i < _rops.length; i++) {
            size = _rops[i].size();
            if (size == Integer.MAX_VALUE) {
                total = size;
                break;
            }
            total += size;
        }
        _size = total;
        return _size;
    }

    @Override
    public void reset() throws Exception {
        for (int i = 0; i < _rops.length; i++)
            if (_status[i] != UNOPENED)
                _rops[i].reset();
        clear();
    }

    @Override
    public void close() throws Exception {
        Exception err = null;
        for (int i = 0; i < _rops.length; i++) {
            try {
                if (_status[i] != UNOPENED)
                    _rops[i].close();
            } catch (Exception e) {
                if (err == null)
                    err = e;
            }
        }

        clear();
        if (err != null)
            throw err;
    }

    private void clear() {
        _cur = null;
        for (int i = 0; i < _rops.length; i++) {
            _status[i] = OPENED;
            if (_values != null)
                _values[i] = null;
            if (_orderValues != null)
                _orderValues[i] = null;
        }
    }

    @Override
    public void handleCheckedException(Exception e) {
        if (_rops.length == 0)
            throw new RuntimeException(e);
        _rops[0].handleCheckedException(e);
    }

    @Override
    public boolean next() throws Exception {
        // initialize all rops with the latest values
        boolean hasValue = false;
        for (int i = 0; i < _status.length; i++) {
            switch (_status[i]) {
                case UNOPENED:
                    // this will only ever be the case if we aren't ordering
                    _rops[i].open();
                    _status[i] = OPENED;
                    // no break
                case OPENED:
                    // if this rop has a value, cache it; if we're not ordering,
                    // then that's the value to return
                    if (_rops[i].next()) {
                        if (_comp == null) {
                            _cur = _rops[i].getResultObject();
                            return true;
                        } else {
                            hasValue = true;
                            _status[i] = VALUE;
                            _values[i] = _rops[i].getResultObject();
                            _orderValues[i] = getOrderingValue(_values[i],
                                i, _rops[i]);
                        }
                    } else
                        _status[i] = DONE;
                    break;
                case VALUE:
                    // we only use this state when ordering
                    hasValue = true;
                    break;
            }
        }

        // if we get to this point without a comparator, it means none
        // of our rops have any more values
        if (_comp == null || !hasValue)
            return false;

        // for all the rops with values, find the 'least' one according to
        // the comparator
        int least = -1;
        Object orderVal = null;
        for (int i = 0; i < _orderValues.length; i++) {
            if (_status[i] != VALUE)
                continue;
            if (least == -1 || _comp.compare(_orderValues[i], orderVal) < 0) {
                least = i;
                orderVal = _orderValues[i];
            }
        }

        // assign the least value to the current one, and clear the cached
        // value for that rop so that we know to get the next value for
        // the next comparison
        _cur = _values[least];
        _values[least] = null;
        _orderValues[least] = null;
        _status[least] = OPENED;
        return true;
    }

    @Override
    public Object getResultObject() throws Exception {
        return _cur;
    }

    /**
     * Return the value to use for ordering on the given result value. Returns
     * the result value by default.
     *
     * @param val the result value
     * @param idx the index of the result object provider in the array
     * given on construction that produced the result value
     * @param rop the result object provider that produced the result value
     */
    protected Object getOrderingValue(Object val, int idx,
        ResultObjectProvider rop) {
        return val;
    }
}
