/*
 * 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.ignite.transactions.spring.examples;

import java.io.Serializable;
import java.util.Objects;
import org.apache.ignite.client.ClientCache;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static org.springframework.transaction.annotation.Isolation.READ_COMMITTED;
import static org.springframework.transaction.annotation.Isolation.REPEATABLE_READ;

/**
 * Represents Spring Service that uses Ignite thin client to access Ignite cluster and perform cache transactional
 * operations.
 */
@Service
public class IgniteClientTransactionalService {
    /** Ignite cache representation that uses thin client to communicate with Ignite cluster. */
    private ClientCache<String, Account> cache;

    /**
     * The emitters transfer the specified funds to the broker. When both funds are received, they are transferred to
     * the recipient, excluding the fee which the broker keeps for himself. If an error occurs at any step of this
     * operation, it is rolled back.
     */
    @Transactional(isolation = REPEATABLE_READ)
    public void transferFundsWithBroker(
        String firstEmitter,
        String secondEmitter,
        String recipient,
        String broker,
        int funds,
        int fee
    ) {
        transferFunds(firstEmitter, broker, funds);

        transferFunds(secondEmitter, broker, funds);

        transferFunds(broker, recipient, funds * 2 - fee);
    }

    /** Transfers funds between two accounts that belong to users with the specified names. */
    @Transactional(isolation = REPEATABLE_READ)
    public void transferFunds(String emitter, String recipient, int funds) {
        Account emitterAcc = cache.get(emitter);
        Account recipientAcc = cache.get(recipient);

        if (emitterAcc.balance < funds)
            throw new RuntimeException("Insufficient funds in " + emitter + "'s account");

        emitterAcc.balance -= funds;
        recipientAcc.balance += funds;

        saveAccount(emitterAcc);
        saveAccount(recipientAcc);

        System.out.println(">>> " + emitter + " transfers " + funds + " coins to " + recipient);
    }

    /** Gets current balance of the account with the specified name.*/
    @Transactional(isolation = READ_COMMITTED)
    public int getBalance(String login) {
        return cache.get(login).balance;
    }

    /** Creates account with the specified user login and balance. */
    public Account createAccount(String login, int balance) {
        Account acc = new Account(login);

        acc.balance = balance;

        cache.put(login, acc);

        return acc;
    }

    /** Sets an Ignite cache representation that uses thin client to communicate with the Ignite cluster. */
    public void setCache(ClientCache<String, Account> cache) {
        this.cache = cache;
    }

    /** Puts the specified account into the cache. */
    private void saveAccount(Account acc) {
        cache.put(acc.login, acc);
    }

    /** Represents the user account. */
    private static class Account implements Serializable {
        /** Account owner login. */
        private final String login;

        /** Balance. */
        private int balance;

        /** Creates an account with the specified owner name. */
        public Account(String login) {
            this.login = login;
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object other) {
            if (this == other)
                return true;

            if (other == null || getClass() != other.getClass())
                return false;

            Account acc = (Account)other;

            return balance == acc.balance && Objects.equals(login, acc.login);
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return Objects.hash(login, balance);
        }
    }
}
