/*--------------------------------------------------------------------------------------*
 *                                                                                      *
 * ZAD - rozwiazanie                                                                    *
 *                                                                                      *
 * graf jest reprezentowany przez 2 kolekcje: kolekcję wierzchołków i kolekcę krawędzi. *
 * Metoda 'delVertex' nie zawsze poprawnie usuwa wierzchołek, który jest argumentem     *
 * Przykład błędnego działania (spodziewamy się usunięcia wierzchołka) jest pokazany    *
 * poniżej. Popraw kod.                                                                 *
 *--------------------------------------------------------------------------------------*/
#include <memory>
#include <vector>
#include <iostream>

using namespace std;

namespace graph {

    struct Edge;
    using PEdge = shared_ptr<Edge>;
    using Edges = vector<PEdge>;

    struct Vertex;
    using PVertex = shared_ptr<Vertex>;
	using PPVertex = weak_ptr<Vertex>;
    using Vertices = vector<PVertex>;

    struct Edge {
        Edge(PVertex in, PVertex out, int len) : in_(in), out_(out), len_(len) { cout << "Edge C-tor " << endl; }
        ~Edge() { cout << "Edge D-tor" << endl; }
        PVertex in_;
        PVertex out_;
        int len_;
    };

	/** rozwiązanie 1: in_, out_ w Edge są typu weak_ptr<Vertex> */

    struct Vertex {
        Vertex(const string& name) : name_(name) { cout << "Vertex C-tor " << name_ << endl; }
        ~Vertex(){ cout << "Vertex D-tor " << name_ << endl; }
        string name_;
    };

    struct Graph {
        Edges edges;
        Vertices vertices;

        PVertex newVertex(const string& name) {
            PVertex v(new Vertex(name));
            vertices.push_back(v);
            return v;
        }

        PEdge newEdge(PVertex in, PVertex out, int len) {
            PEdge e(new Edge(in,out,len) );
            edges.push_back(e);
            return e;
        }

		/** rozwiązanie 2: usuwać powiązanie pomiędzy krawędzią a 'v', np. przez 'reset' albo usunięcie krawędzi */

        void delVertex(PVertex v) {
            for(Vertices::iterator i = vertices.begin(); i != vertices.end(); ) {
                if(*i == v) {
                    cout << "Del vertex " << (*i)->name_ <<  endl;
                    i = vertices.erase(i);
                }
				else {
					++i;
				}
            }
        }
    };

} //namespace Graph

using namespace graph;

int main() {

    Graph g;
    {
        PVertex v1 = g.newVertex("A");
        PVertex v2 = g.newVertex("B");
        PEdge e = g.newEdge(v1, v2, 10);
        g.delVertex(v1);
    }
	return 0;
}
