package com.wrox.algorithms.queues;

import com.wrox.algorithms.iteration.Iterator;
import com.wrox.algorithms.lists.ArrayList;
import com.wrox.algorithms.lists.List;

public class CallCenter {
    /** kolejka zgłoszeń */
    private final Queue _calls = new BlockingQueue(new ListFifoQueue());

    /** liczba działających konsultantów */
    private final int _numberOfAgents;

    /**  lista wątków konsultantów 
      */ pusta, gdy centrum zamknięte, i niepusta, gdy otwarte
      */
    private final List _threads;

    /**
     * Konstruktor.
     * parametr: liczba działających konsultantów
     */
    public CallCenter(int numberOfAgents) {
        _threads = new ArrayList(numberOfAgents);
        _numberOfAgents = numberOfAgents;
    }


    public void open() {
        assert _threads.isEmpty() : "Centrum obsługi jest już otwarte";

        System.out.println("Otwieranie centrum obsługi");

        for (int i = 0; i < _numberOfAgents; ++i) {
            Thread thread = new Thread(new CustomerServiceAgent(i, _calls));

            thread.start();
            _threads.add(thread);
        }

        System.out.println("Centrum obsługi otwarte");
    }


    public void accept(Call call) {
        assert !_threads.isEmpty() : "Centrum obsługi jest zamknięte";

        _calls.enqueue(call);

        System.out.println(call + " umieszczone w kolejce");
    }



    public void close() {
        assert !_threads.isEmpty() : "Centrum obsługi jest już zamknięte";

        System.out.println("Zamykanie centrum obsługi");

        // wysłanie "zgłoszenia kończącego" do każdego z agentów
        for (int i = 0; i < _numberOfAgents; ++i) {
            accept(CustomerServiceAgent.GO_HOME); 
        }

        Iterator i = _threads.iterator();
        for (i.first(); !i.isDone(); i.next()) {
            waitForTermination((Thread) i.current());
        }

        _threads.clear();

        System.out.println("Centrum obsługi jest zamknięte");
    }


    private void waitForTermination(Thread thread) {
        try {
            thread.join();
        } catch (InterruptedException e) {
            // Ignoruj
        }
    }


}
