package edu.kit.prog1314.shop.util;

import edu.kit.prog1314.shop.*;

import java.util.Iterator;

/**
 * A class representing a graph of articles.
 * 
 * @author Janis Schötterl-Glausch
 * @author Raphael von der Grün
 * @version 2
 */
public class Graph {
    private List<Edge> edges = new List<>();

    /**
     * Creates an empty Graph.
     */
    public Graph() { }

    /**
     * Initialize a graph with the articles and their relations given by a shop.
     * 
     * @param shop
     *            The Shop
     */
    public Graph(Shop shop) {
        for (Order order : shop.getOrders()) {
            for (Article article : order.getArticles()) {
                Iterator<Article> iter = order.getArticles().iterator();
                while (!iter.next().equals(article)) { }
                while (iter.hasNext()) {
                    edges.addUnique(new Edge(article, iter.next())).weight++;
                }
            }
        }
    }

    /**
     * Returns a graph representing the vertices reachable from an article.
     * 
     * @param article
     *            The article from witch to calculate the neighbourhood.
     * @return The neighbourhood graph
     */
    public Graph neighbourhood(Article article) {
        Graph nei = new Graph();
        for (Edge edge : edges) {
            if (edge.includes(article)) {
                nei.edges.add(edge);
            }
        }
        return nei;
    }

    /**
     * Returns the edge with the maximum weight.
     * 
     * @return The edge with the maximum weight, null if there are no edges; in
     *         case of a tie one of the maximum edges is chosen.
     */
    public Edge getMaximum() {
        Edge dummy = new Edge(null, null);
        Edge max = dummy;
        for (Edge edge : edges) {
            if (edge.weight > max.weight) {
                max = edge;
            }
        }
        return max == dummy ? null : max;
    }

    /**
     * A class representing an undirected edge.
     * 
     * @author Janis Schötterl-Glausch
     * @author Raphael von der Grün
     * @version 2
     */
    public static final class Edge {
        private Article article1;
        private Article article2;
        private int weight;

        private Edge(Article article1, Article article2) {
            this.article1 = article1;
            this.article2 = article2;
        }

        /**
         * Returns one of the vertices.
         * 
         * @return A vertex.
         */
        public Article getFirst() {
            return article1;
        }

        /**
         * Returns the other vertex.
         * 
         * @return A vertex.
         */
        public Article getSecond() {
            return article2;
        }

        @Override
        public boolean equals(Object o) {
            if (o != null && o instanceof Edge) {
                Edge other = (Edge) o;
                return includes(other.article1) && includes(other.article2);
            }
            return false;
        }

        /**
         * Checks if this edge includes the given article.
         * 
         * @param article
         *            the article to check for
         * @return true if this edge includes the given article, false otherwise
         */
        private boolean includes(Article article) {
            return article1.equals(article) || article2.equals(article);
        }
    }
}
