#undef DEBUG
using System;

namespace OOP_Polymorphie
{
    class Shape
    {
        // Referenzpunkt zum Verschieben und Positionieren der Form
        protected Point rp = new Point();

        // Konstruktoren
        public Shape() { }
        public Shape(Point p)
        {
            rp = p;
        }
        public Shape(int x, int y)
        {
            rp.x = x;
            rp.y = y;
        }

        // Methode zum Verschieben, wird von allen abgeleiteten Klassen genutzt
        public void Move(int dx, int dy)
        {
            rp.x += dx;
            rp.y += dy;
        }

        // Umwandlung in String
        public override string ToString()
        {
            return String.Format(" Form ({0},{1}) ", rp.x, rp.y);
        }

        // Methode zum Zeichen, wird von abgeleiteten Klassen überschrieben
        public virtual void Draw()
        {
            Console.WriteLine(" Form ({0},{1}) ", rp.x, rp.y);
        }
    }

    // Abgeleitete Klassen
    class Line : Shape
    {
        protected Point start;
        protected Point end;

        public Line(Point s, Point e)
            : base(s)
        {
            start = s;
            end = e;
        }

        public override void Draw()
        {
            Console.WriteLine(" Linie ({0},{1}) ", rp.x, rp.y);
        #if DEBUG
            Console.WriteLine("\t\t ({0},{1}) bis ({2},{3}) ", start.x, start.y, end.x, end.y);
        #endif
        }
    }

    class Circle : Shape
    {
        protected Point center;
        protected int radius;

        public Circle(Point p, int r)
            : base(p)
        {
            center = p;
            radius = r;
        }

        public override void Draw()
        {
            Console.WriteLine(" Circle ({0},{1}) ", rp.x, rp.y);
        #if DEBUG
            Console.WriteLine("\t\t Center ({0},{1}), Radius {2} ", center.x, center.y, radius);
        #endif
        }
    }

    class Polygon : Shape
    {
        protected Point[] nodes;

        public Polygon(Point[] nodes)
            : base(nodes[0])
        {
            this.nodes = nodes;
        }

        public override void Draw()
        {
            Console.WriteLine(" Polygon ({0},{1}) ", rp.x, rp.y);
        #if DEBUG
            Console.Write("\t\t ");
            foreach (Point p in nodes)
                Console.Write("({0},{1}) ", p.x, p.y);
            Console.WriteLine();
        #endif
        }
    }



    class Rectangle : Polygon
    {
        public Rectangle(Point lo, Point lu, Point ro, Point ru)
            : base(new Point[4] { lo, lu, ro, ru })
        {
        }

        public override void Draw()
        {
            Console.WriteLine(" Rechteck ({0},{1}) ", rp.x, rp.y);
        #if DEBUG
            Console.Write("\t\t ");
            foreach (Point p in nodes)
                Console.Write("({0},{1}) ", p.x, p.y);
            Console.WriteLine();
        #endif
        }
    }

    class Square : Polygon
    {
        public Square(Point lo, int width)
            : base(new Point[4] {lo, 
                                      new Point(lo.x, lo.y - width), 
                                      new Point(lo.x + width, lo.y), 
                                      new Point(lo.x + width, lo.y - width)})
        {
        }

        public override void Draw()
        {
            Console.WriteLine(" Quadrat ({0},{1}) ", rp.x, rp.y);
        #if DEBUG
            Console.Write("\t\t ");
            foreach (Point p in nodes)
                Console.Write("({0},{1}) ", p.x, p.y);
            Console.WriteLine();
        #endif
        }
    }
}
