/*
 *
 * 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.
 *
 */
#ifndef _tests_TxMocks_h
#define _tests_TxMocks_h


#include "qpid/Exception.h"
#include "qpid/Msg.h"
#include "qpid/broker/TransactionalStore.h"
#include "qpid/broker/TxOp.h"
#include <iostream>
#include <vector>

using namespace qpid::broker;
using boost::static_pointer_cast;
using std::string;

namespace qpid {
namespace tests {

template <class T> void assertEqualVector(std::vector<T>& expected, std::vector<T>& actual){
    unsigned int i = 0;
    while(i < expected.size() && i < actual.size()){
        BOOST_CHECK_EQUAL(expected[i], actual[i]);
        i++;
    }
    if (i < expected.size()) {
        throw qpid::Exception(QPID_MSG("Missing " << expected[i]));
    } else if (i < actual.size()) {
        throw qpid::Exception(QPID_MSG("Extra " << actual[i]));
    }
    BOOST_CHECK_EQUAL(expected.size(), actual.size());
}

class TxOpConstants{
protected:
    const string PREPARE;
    const string COMMIT;
    const string ROLLBACK;

    TxOpConstants() : PREPARE("PREPARE"), COMMIT("COMMIT"), ROLLBACK("ROLLBACK") {}
};

class MockTxOp : public TxOp, public TxOpConstants{
    std::vector<string> expected;
    std::vector<string> actual;
    bool failOnPrepare;
    string debugName;
public:
    typedef boost::shared_ptr<MockTxOp> shared_ptr;

    MockTxOp() : failOnPrepare(false) {}
    MockTxOp(bool _failOnPrepare) : failOnPrepare(_failOnPrepare) {}

    void setDebugName(string name){
        debugName = name;
    }

    void printExpected(){
        std::cout << std::endl << "MockTxOp[" << debugName << "] expects: ";
        for (std::vector<string>::iterator i = expected.begin(); i < expected.end(); i++) {
            if(i != expected.begin()) std::cout << ", ";
            std::cout << *i;
        }
        std::cout << std::endl;
    }

    void printActual(){
        std::cout << std::endl << "MockTxOp[" << debugName << "] actual: ";
        for (std::vector<string>::iterator i = actual.begin(); i < actual.end(); i++) {
            if(i != actual.begin()) std::cout << ", ";
            std::cout << *i;
        }
        std::cout << std::endl;
    }

    bool prepare(TransactionContext*) throw(){
        actual.push_back(PREPARE);
        return !failOnPrepare;
    }
    void commit()  throw(){
        actual.push_back(COMMIT);
    }
    void rollback()  throw(){
        if(!debugName.empty()) std::cout << std::endl << "MockTxOp[" << debugName << "]::rollback()" << std::endl;
        actual.push_back(ROLLBACK);
    }

    void callObserver(const boost::shared_ptr<TransactionObserver>&) {}

    MockTxOp& expectPrepare(){
        expected.push_back(PREPARE);
        return *this;
    }
    MockTxOp& expectCommit(){
        expected.push_back(COMMIT);
        return *this;
    }
    MockTxOp& expectRollback(){
        expected.push_back(ROLLBACK);
        return *this;
    }
    void check(){
        assertEqualVector(expected, actual);
    }

    ~MockTxOp(){}
};

class MockTransactionalStore : public TransactionalStore{
    const string BEGIN;
    const string BEGIN2PC;
    const string PREPARE;
    const string COMMIT;
    const string ABORT;
    std::vector<string> expected;
    std::vector<string> actual;

    enum states {OPEN = 1, PREPARED = 2, COMMITTED = 3, ABORTED = 4};
    int state;

    class TestTransactionContext : public TPCTransactionContext{
        MockTransactionalStore* store;
    public:
        TestTransactionContext(MockTransactionalStore* _store) : store(_store) {}
        void prepare(){
            if(!store->isOpen()) throw "txn already completed";
            store->state = PREPARED;
        }

        void commit(){
            if(!store->isOpen() && !store->isPrepared()) throw "txn already completed";
            store->state = COMMITTED;
        }

        void abort(){
            if(!store->isOpen() && !store->isPrepared()) throw "txn already completed";
            store->state = ABORTED;
        }
        ~TestTransactionContext(){}
    };

public:
    MockTransactionalStore() :
            BEGIN("BEGIN"), BEGIN2PC("BEGIN2PC"), PREPARE("PREPARE"), COMMIT("COMMIT"), ABORT("ABORT"),  state(OPEN){}

    void collectPreparedXids(std::set<std::string>&)
    {
        throw "Operation not supported";
    }

    std::auto_ptr<TPCTransactionContext> begin(const std::string&){
        actual.push_back(BEGIN2PC);
        std::auto_ptr<TPCTransactionContext> txn(new TestTransactionContext(this));
        return txn;
    }
    std::auto_ptr<TransactionContext> begin(){
        actual.push_back(BEGIN);
        std::auto_ptr<TransactionContext> txn(new TestTransactionContext(this));
        return txn;
    }
    void prepare(TPCTransactionContext& ctxt){
        actual.push_back(PREPARE);
        dynamic_cast<TestTransactionContext&>(ctxt).prepare();
    }
    void commit(TransactionContext& ctxt){
        actual.push_back(COMMIT);
        dynamic_cast<TestTransactionContext&>(ctxt).commit();
    }
    void abort(TransactionContext& ctxt){
        actual.push_back(ABORT);
        dynamic_cast<TestTransactionContext&>(ctxt).abort();
    }
    MockTransactionalStore& expectBegin(){
        expected.push_back(BEGIN);
        return *this;
    }
    MockTransactionalStore& expectBegin2PC(){
        expected.push_back(BEGIN2PC);
        return *this;
    }
    MockTransactionalStore& expectPrepare(){
        expected.push_back(PREPARE);
        return *this;
    }
    MockTransactionalStore& expectCommit(){
        expected.push_back(COMMIT);
        return *this;
    }
    MockTransactionalStore& expectAbort(){
        expected.push_back(ABORT);
        return *this;
    }
    void check(){
        assertEqualVector(expected, actual);
    }

    bool isPrepared(){
        return state == PREPARED;
    }

    bool isCommitted(){
        return state == COMMITTED;
    }

    bool isAborted(){
        return state == ABORTED;
    }

    bool isOpen() const{
        return state == OPEN;
    }
    ~MockTransactionalStore(){}
};

}} // namespace qpid::tests

#endif
