package de.tu_dresden.diplom.richter_mirko_mat2628335.witness.account;

import org.apache.log4j.Logger;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.entity.IFEntity;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.account.IFAccountIdentification;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.account.Amount;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.account.IFCurrency;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.account.IFAmount;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.keystore.ApplicationSpecificKeystoreUtility;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.info.account.IFAccountInfoItem;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.info.account.AccountInfoItem;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.info.account.AccountInfoItem;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.info.account.IFAccountInfoItem;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.entity.IFEntity;

import java.util.*;

/**
 * 
 */
public class AccountPool {

   private static final Logger logger = Logger.getLogger(AccountPool.class);

   private static Map[] accounts = null;

   static {
      resetAccounts();
   }

   public static IFAccount getAccount(IFEntity entity, IFAccountIdentification accountIdent) {
      Map mapOfIdentity = getMapOfIdentity(entity.getId());
      return (IFAccount) mapOfIdentity.get(accountIdent.getId());
   }

   public static IFAccount[] getAccounts(IFEntity entity){
      final String fn = "[getAccounts] ";
      IFAccount[] result = null;
      if(entity != null){
         Map mapOfIdentity = getMapOfIdentity(entity.getId());
         if(mapOfIdentity != null && mapOfIdentity.size() > 0){
            Collection values = mapOfIdentity.values();
            result = (IFAccount[]) values.toArray(new IFAccount[mapOfIdentity.size()]);
         }else{
            if(logger.isInfoEnabled())logger.info(fn + "no accounts found for entity '" + entity + "'");
         }
      }else{
         logger.error(fn + "CHECK FOR PARAMS FAILED: entity ws NULL!");
      }
      return result;
   }

   public static IFAccountInfoItem[] getAccountInfos(IFEntity entity){
      final String fn = "[getAccountInfos] ";
      IFAccountInfoItem[] result = null;
      if(entity != null){
         Map mapOfIdentity = getMapOfIdentity(entity.getId());
         if(mapOfIdentity != null && mapOfIdentity.size() > 0){
            Set keys = mapOfIdentity.keySet();
            result = new IFAccountInfoItem[mapOfIdentity.size()];
            int pos = 0;
            for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
               String accountID = (String) iterator.next();
               IFAccount account = (IFAccount) mapOfIdentity.get(accountID);
               AccountInfoItem item = new AccountInfoItem(accountID, new Amount(account.getAmount()));
               item.setOwnerIdentityID(entity.getId());
               item.setOwnerIdentityDescription(entity.toString());
               result[pos] = item;
               pos++;
            }
         }else{
            if(logger.isInfoEnabled())logger.info(fn + "no accounts found for entity '" + entity + "'");
         }
      }else{
         logger.error(fn + "CHECK FOR PARAMS FAILED: entity ws NULL!");
      }
      return result;
   }

   public static void createAccount(IFEntity entity, IFAccountIdentification accountId, IFAmount newAmount){
      final String fn = "[createAccount] ";
      if(entity != null && accountId != null && accountId.getId() != null && newAmount != null){
         Map mapOfIdentity = getMapOfIdentity(entity.getId());
         if(mapOfIdentity == null){
            mapOfIdentity = new HashMap();
            registerMapOfIdentity(entity.getId(), mapOfIdentity);
         }
         if(mapOfIdentity.containsKey(accountId.getId())){
            if(logger.isInfoEnabled())logger.info(fn + "overwriting existing account with id '" + accountId.getId() + "'");
         }
         Account newAccount = new Account(newAmount);
         newAccount.setIdentification(accountId.getId());
         mapOfIdentity.put(accountId.getId(), newAccount);
      }else{
         StringBuffer err = new StringBuffer("PARAM CHECK FAILED: ");
         if(entity == null){
            err.append("entity was NULL!");
         }else if(accountId == null){
            err.append("accountId was NULL!");
         }else if(accountId.getId() == null){
            err.append("accountId.ident was NULL!");
         }else if(newAmount == null){
            err.append("newAmount was NULL!");
         }
         logger.error(fn + err);
      }
   }

   public static void resetAccounts(){
      int entityCount = ApplicationSpecificKeystoreUtility.SIG_ALIASES.length;
      accounts = new Map[entityCount];
      Map client = new HashMap();
      {
         Account def = new Account(null);
         String id = "default";
         def.setIdentification(id);
         def.setAmount(new Amount(200, IFCurrency.CURRENCY_COUNTER_INST));
         client.put(id, def);

         Account one = new Account(null);
         id = "one";
         one.setIdentification(id);
         one.setAmount(new Amount(150, IFCurrency.CURRENCY_COUNTER_INST));
         client.put(id, one);

         Account two = new Account(null);
         id = "two";
         two.setIdentification(id);
         two.setAmount(new Amount(100, IFCurrency.CURRENCY_COUNTER_INST));
         client.put(id, two);
      }
      accounts[ApplicationSpecificKeystoreUtility.ENTITY_CLIENT1] = client;

      Map ticketBooking = new HashMap();
      {
         Account def = new Account(null);
         String id = "default";
         def.setIdentification(id);
         def.setAmount(new Amount(200, IFCurrency.CURRENCY_COUNTER_INST));
         ticketBooking.put(id, def);

         Account one = new Account(null);
         id = "one";
         one.setIdentification(id);
         one.setAmount(new Amount(150, IFCurrency.CURRENCY_COUNTER_INST));
         ticketBooking.put(id, one);
      }
      accounts[ApplicationSpecificKeystoreUtility.ENTITY_TICKET_BOOKING] = ticketBooking;

      Map ticketReservation = new HashMap();
      {
         Account def = new Account(null);
         String id = "default";
         def.setIdentification(id);
         def.setAmount(new Amount(200, IFCurrency.CURRENCY_COUNTER_INST));
         ticketReservation.put(id, def);

         Account one = new Account(null);
         id = "one";
         one.setIdentification(id);
         one.setAmount(new Amount(150, IFCurrency.CURRENCY_COUNTER_INST));
         ticketReservation.put(id, one);
      }
      accounts[ApplicationSpecificKeystoreUtility.ENTITY_TICKET_RESERVATION] = ticketReservation;
   }

   private static Map getMapOfIdentity(int id){
      Map result = null;
      if(id >= 0 && id < accounts.length){
         result = (Map) accounts[id];
      }
      return result;
   }

   private static void registerMapOfIdentity(int id, Map mapOfIdentity){
      if(id >= 0 && id < accounts.length){
         accounts[id] = mapOfIdentity;
      }
   }

}
