package ru.agolovin;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author agolovin (agolovin@list.ru)
 * @version $Id$
 * @since 0.1
 */

class Book {

    /**
     * All orders.
     */
    private Map<Integer, Order> orders = new HashMap<>();

    /**
     * sell book.
     */
    private Map<Float, Order> sellBook = new TreeMap<>();

    /**
     * buy book.
     */
    private Map<Float, Order> buyBook = new TreeMap<>(Comparator.reverseOrder());

    /**
     * Buy order.
     */
    private Order buyOrder;

    /**
     * sell order.
     */
    private Order sellOrder;

    /**
     * add order to map.
     *
     * @param order Order.
     */
    void add(Order order) {
        orders.put(order.getId(), order);
    }

    /**
     * delete order in the map by id.
     *
     * @param orderId int.
     */
    void delete(Integer orderId) {
        orders.remove(orderId);
    }

    /**
     * replace orders.
     */
    private void replace() {
        for (Map.Entry<Integer, Order> element : orders.entrySet()) {
            if ("BUY".equals(element.getValue().getType())) {
                Order newOrder = buyBook.get(element.getValue().getPrice());
                if (newOrder != null) {
                    newOrder.setVolume(newOrder.getVolume()
                            + element.getValue().getVolume());
                } else {
                    buyBook.put(element.getValue().getPrice(), element.getValue());
                }
            } else {
                Order temp = sellBook.get(element.getValue().getPrice());
                if (temp != null) {
                    temp.setVolume(temp.getVolume() + element.getValue().getVolume());
                } else {
                    sellBook.put(element.getValue().getPrice(), element.getValue());
                }
            }
        }

    }

    /**
     * set orders.
     */
    private void work() {
        Iterator<Float> buyIterator = buyBook.keySet().iterator();
        Iterator<Float> sellIterator = sellBook.keySet().iterator();

        Float nextBuy = buyIterator.next();
        Float nextSell = sellIterator.next();

        List<Float> buyDel = new ArrayList<>();
        List<Float> sellDel = new ArrayList<>();

        boolean flag = false;

        do {
            this.buyOrder = this.buyBook.get(nextBuy);
            this.sellOrder = this.sellBook.get(nextSell);
            if (this.buyOrder.getPrice() >= this.sellOrder.getPrice()) {
                if (this.buyOrder.getVolume() > this.sellOrder.getVolume()) {
                    this.buyOrder.setVolume(this.buyOrder.getVolume() - this.sellOrder.getVolume());
                    nextSell = sellIterator.next();
                    sellDel.add(this.buyOrder.getPrice());
                } else if (this.buyOrder.getVolume() < this.sellOrder.getVolume()) {
                    this.sellOrder.setVolume(this.sellOrder.getVolume() - this.buyOrder.getVolume());
                    nextBuy = buyIterator.next();
                    buyDel.add(this.buyOrder.getPrice());
                } else {
                    this.buyBook.remove(this.buyOrder.getPrice());
                    this.sellBook.remove(this.sellOrder.getPrice());
                    nextBuy = buyIterator.next();
                    nextSell = sellIterator.next();
                }
            } else {
                flag = true;
            }
        } while (!flag);

        this.buyBook = removeUnused(buyDel, buyBook);

        this.sellBook = removeUnused(sellDel, sellBook);
    }

    /**
     * removeunused orders.
     *
     * @param list List
     * @param book Map
     * @return Map
     */
    private Map<Float, Order> removeUnused(List<Float> list, Map<Float, Order> book) {
        for (Float element : list) {
            book.remove(element);
        }
        return book;
    }

    /**
     * initialization.
     */
    void init() {
        replace();
        work();
        Iterator<Float> buyIterator = buyBook.keySet().iterator();
        Iterator<Float> sellIterator = sellBook.keySet().iterator();

        Float nextBuy;
        Float nextSell;

        while (buyIterator.hasNext() && sellIterator.hasNext()) {
            nextBuy = buyIterator.next();
            nextSell = sellIterator.next();

            buyOrder = buyBook.get(nextBuy);
            sellOrder = sellBook.get(nextSell);

            System.out.print(
                    String.format(
                            "%7s @ %s", buyOrder.getVolume(),
                            buyOrder.getPrice()));
            System.out.println(
                    String.format(
                            " - %s @ %s", sellOrder.getPrice(),
                            sellOrder.getVolume()));
        }
    }
}

@@ -2857,35 +2857,36 @@
 ellDel.add(this.
-buy
+sell
 Order.getPrice()
@@ -4814,66 +4814,997 @@
 .get
-Price(),%0A                            sellOrder.getVolume()
+Volume(),%0A                            sellOrder.getPrice()));%0A        %7D%0A%0A        if (buyIterator.hasNext()) %7B%0A            do %7B%0A                buyOrder = buyBook.get(buyIterator.next());%0A                System.out.print(%0A                        String.format(%0A                                %22%257s @ %25s%22, buyOrder.getVolume(),%0A                                buyOrder.getPrice()));%0A                System.out.println(%0A                        String.format(%0A                                %22 - %256s%22, %22------%22));%0A            %7D while (buyIterator.hasNext());%0A        %7D else if (sellIterator.hasNext()) %7B%0A            do %7B%0A                sellOrder = sellBook.get(sellIterator.next());%0A                System.out.print(String.format(%22%2514s%22, %22------%22));%0A                System.out.println(%0A                        String.format(%0A                                %22 - %25s @ %25s%22, sellOrder.getVolume(),%0A                                sellOrder.getPrice()));%0A            %7D while (sellIterator.hasNext(
 ));%0A

add task2 in part7 chapter5 package2