/***************************************************************************
                          parabolas.cpp  -  description
                             -------------------
    begin                : Sam Mai 4 2002
    copyright            : (C) 2002 by Birgit Schulz
    email                : B.Schulz@Superlehrer.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "parabolas.h"
#include "parabolas.moc"


#include <math.h>

#include <krestrictedline.h>
#include <kpushbutton.h>
#include <ktextbrowser.h>
#include <klocale.h>
#include <kapplication.h>

#include <qlabel.h>
#include <qstring.h>

Parabolas::Parabolas(QWidget *parent, const char *name ) : ParabolasD(parent,name)
    {
        
    }
Parabolas::~Parabolas(){
}

void Parabolas::changeView(EFunctions eSelected)
{
    //Clear Boxes
    KTextBrowserResult->setText("");
    KRestrictedLineInfo1->setText("");
    KRestrictedLineInfo2->setText("");
    KRestrictedLineInfo3->setText("");
    
    //Enable 2. and 3. Label/KRestrictedLine
    TextLabelInfo2->show();
    TextLabelInfo3->show();
    KRestrictedLineInfo2->show();
    KRestrictedLineInfo3->show();

    switch (eSelected)
    {
        case AxisSection:
        {
            TextLabelInformation->setText(i18n("Find intersection with axis"));
            TextLabelInfo1->setText(i18n("Parabola equation  y ="));
            KRestrictedLineInfo1->setValidChars("0123456789+-.()x^*");
            KTextBrowserResult->setText("");

            TextLabelInfo2->hide();
            TextLabelInfo3->hide();
            KRestrictedLineInfo2->hide();
            KRestrictedLineInfo3->hide();

            m_eSelected = AxisSection;

        }
        break;

        case Scheitel:
        {
            TextLabelInformation->setText(i18n("Find vertex of a parabola"));
            TextLabelInfo1->setText(i18n("Parabola equation  y ="));
            KRestrictedLineInfo1->setValidChars("0123456789+-.()x^*");
            KTextBrowserResult->setText("");

            TextLabelInfo2->hide();
            TextLabelInfo3->hide();
            KRestrictedLineInfo2->hide();
            KRestrictedLineInfo3->hide();

            m_eSelected = Scheitel;
        }
        break;

        case FindStandard:
        {
            TextLabelInformation->setText(i18n("Find standard-parabola with vertex"));
            TextLabelInfo1->setText(i18n("Vertex  S:"));
            KRestrictedLineInfo1->setValidChars("0123456789+-.()|x");
            KTextBrowserResult->setText("");

            TextLabelInfo2->hide();
            TextLabelInfo3->hide();
            KRestrictedLineInfo2->hide();
            KRestrictedLineInfo3->hide();

            m_eSelected = FindStandard;
        }
        break;

        case ThreePoints:
        {
            TextLabelInformation->setText(i18n("Find equation of a parabola with three points"));
            TextLabelInfo1->setText(i18n("First point  P:"));
            KRestrictedLineInfo1->setValidChars("0123456789+-.()x|");
            TextLabelInfo2->setText(i18n("Second point  Q:"));
            KRestrictedLineInfo2->setValidChars("0123456789+-.()x|");
            TextLabelInfo3->setText(i18n("Third point  R:"));
            KRestrictedLineInfo3->setValidChars("0123456789+-.()x|");
            TextLabelInfo2->setEnabled(true);
            KRestrictedLineInfo2->setEnabled(true);
            TextLabelInfo3->setEnabled(true);
            KRestrictedLineInfo3->setEnabled(true);
            KTextBrowserResult->setText("");

            m_eSelected = ThreePoints;
        }
        break;

        case ScheitelAndPoint:
        {
            TextLabelInformation->setText(i18n("Find equation of a parabola with vertex and point"));
            TextLabelInfo1->setText(i18n("Vertex  S:"));
            KRestrictedLineInfo1->setValidChars("0123456789-.()|");
            TextLabelInfo2->setText(i18n("One (other) Point P:"));
            KRestrictedLineInfo2->setValidChars("0123456789-.()|");
            TextLabelInfo2->setEnabled(true);
            KRestrictedLineInfo2->setEnabled(true);
            KTextBrowserResult->setText("");
            
            TextLabelInfo3->hide();
            KRestrictedLineInfo3->hide();

            m_eSelected = ScheitelAndPoint;
        }
        break;

        case LineSection:
        {
            TextLabelInformation->setText(i18n("Find section(s) with line"));
            TextLabelInfo1->setText(i18n("Parabola equation  y ="));
            KRestrictedLineInfo1->setValidChars("0123456789+-.x^*");
            TextLabelInfo2->setText(i18n("Line equation  y ="));
            KRestrictedLineInfo2->setValidChars("0123456789+-.x*");
            KTextBrowserResult->setText("");
            TextLabelInfo2->setEnabled(true);
            KRestrictedLineInfo2->setEnabled(true);

            TextLabelInfo3->hide();
            KRestrictedLineInfo3->hide();

            m_eSelected = LineSection;
        }
        break;

        case ParabolaSection:
        {
            TextLabelInformation->setText(i18n("Find section with parabola"));
            TextLabelInfo1->setText(i18n("First parabola equation  y ="));
            KRestrictedLineInfo1->setValidChars("0123456789+-.()x^*");
            TextLabelInfo2->setText(i18n("Second parabola equation  y ="));
            KRestrictedLineInfo2->setValidChars("0123456789+-.()x^*");
            TextLabelInfo2->setEnabled(true);
            KRestrictedLineInfo2->setEnabled(true);
            KTextBrowserResult->setText("");

            TextLabelInfo3->hide();
            KRestrictedLineInfo3->hide();

            m_eSelected = ParabolaSection;
        }
        break;
    }
}

void Parabolas::slotCalculate()
{
switch (m_eSelected)
    {
    case Scheitel: //Find the scheitel of the given parabola
        {
            double a, b, c;
            QString qsResult, qsYs, qsXs;
            
            int iParabola = sscanf(KRestrictedLineInfo1->text().utf8(), " %lf*x^2 %lf*x %lf )", &a, &b, &c);
            if (iParabola == 3)
            {
                if (a == 0)
                {
                    qsResult = "The given equation is <b>not the equation of a parabola</b>! So the vertex can't be found";
                
                }
                else
                {
                    qsXs = "";
                    qsYs = "";
                    double xs = b / (-2.0*a);
                    double ys = c-b*b/(4.0*a);
                    qsXs = qsXs.arg(xs);
                    qsYs = qsYs.arg(ys);
                    qsResult = "The vertex of the given Parabola is <b>S(" + qsXs + "|" + qsYs + ")</b>.";
                    
                    
                }
                KTextBrowserResult->setText(qsResult);
            }
            else
            {
                qsResult = i18n("<font color=red size=+1><b>Incorrect format!</b></font> <p> Enter parabolas like <b><i>a*x^2+b*x+c</i></b><p>");
                qsResult += i18n("Even 1 and 0 as a factor or an addend is still needed.");
                KTextBrowserResult->setText(qsResult);
            }
            break;
        }
    
    case AxisSection: //Find Section Points of the parabola and the axises
        {
            double a, b, c;
            QString qsResult, qsYs, qsX1s, qsX2s, qsC;
            
            int iParabola = sscanf(KRestrictedLineInfo1->text().utf8(), " %lf*x^2 %lf*x %lf )", &a, &b, &c);
            if (iParabola == 3)
            {
                if (a == 0)
                {
                    qsResult = "The given equation is <b>not the equation of a parabola</b>! So the vertex can't be found";
                
                }
                else
                {
                    double d = b*b / (4 * a*a) - c / a;
                    if (d > 0)
                    {
                        double xs1 = b / (-2*a) + sqrt(d); 
                        double xs2 = b / (-2*a) - sqrt(d); 
                        qsX1s = qsX1s.arg(xs1);
                        qsX2s = qsX2s.arg(xs2);
                        qsC = qsC.arg(c);
                        qsResult = "The given parabola has the <font color = red><b>two</b></font> intersection-points with the x-axis<br> "; 
                        qsResult += "<b>Sx<sub>1</sub>(" + qsX1s + "| 0 )</b> and <b>Sx<sub>1</sub>(" + qsX2s + "| 0 )</b> ";
                        qsResult += "and with the y-axis the intersection-point <b>Sy( 0 |" + qsC+" )</b>.";
                        
                    }
                    else
                    {
                        if (d == 0)
                        {
                            double xs1 = b / (-2*a);
                            qsX1s = qsX1s.arg(xs1);
                            qsC = qsC.arg(c);
                            qsResult = "The given parabola has only <font color = red><b>one</b></font> intersection-point with the x-axis<br> "; 
	                        qsResult += "<b>Sx(" + qsX1s + "| 0 )</b>";
    	                    qsResult += "and with the y-axis the intersection-point<br> <b>Sy( 0 |" + qsC+" )</b>.";
        
                        }
                        else
                        {
                            qsC = qsC.arg(c);
                            qsResult = "The given parabola has <font color = red><b>no</b></font> intersection-point with the x-axis<br> "; 
                            if (a > 0)
                            {
                                qsResult += "because it is completely over the x-axis.<br>";
                            }
                            else
                            {
                                qsResult += "because it is completely under the x-axis.<br>";
                            }
                            	
                            qsResult += "The intersection-point with the y-axis the intersection-point<br> <b>Sy( 0 |" + qsC+" )</b>.";
                        }
                    }
                    
                    
                }
                KTextBrowserResult->setText(qsResult);
            }
            else
            {
                qsResult = i18n("<font color=red size=+1><b>Incorrect format!</b></font> <p> Enter parabolas like <b><i>a*x^2+b*x+c</i></b><p>");
                qsResult += i18n("Even 1 and 0 as a factor or an addend is still needed.");
                KTextBrowserResult->setText(qsResult);
            }
            break;
            break;
        }
        
    case FindStandard: //Find equation of standard-parabola with given vertex
        {
            double xs, ys, b, c;
            QString qsB, qsC,qsResult, qsEquation;
            int iPoint = sscanf(KRestrictedLineInfo1->text().utf8(), "( %lf | %lf )", &xs, &ys);
            if (iPoint == 2)
            {
                b = (-2)*xs;
                c = xs*xs + ys;
                qsB = qsB.arg(b);
                qsC = qsC.arg(c);
                qsResult = "The <b>equation of the standard-parabola</b> with the given vertex is<br>";
                qsEquation = "y = x <sup>2</sup> ";
                //Looking for good format with parameter b                                                                 if (b == 0)
                if (b == 0)
                {
                    //Nothing to do :-)
                }
                else if (b > 0)
                {
                    qsEquation += "+ " + qsB + "*x ";
                }
                else
                {
                    qsEquation +=  qsB + "*x ";
                }
                //Looking for good format with parameter c
                if (c == 0)
                {
                    qsEquation += ".";
                }
                else if (c > 0)
                {
                    qsEquation += "+ " + qsC + ".";
                }
                else
                {
                    qsEquation += qsC + ".";
                }
                qsEquation.simplifyWhiteSpace();
                qsResult += qsEquation;
                KTextBrowserResult->setText(qsResult);
            }
            else
            {
                KTextBrowserResult->setText(i18n("<font color=red size=+1><b>Incorrect format!</b></font> <p> Enter points like <b><i>(x<sub>1</sub>|x<sub>2</sub>)</i></b>"));
            }
            break;
        }
    
        
    case ThreePoints: //Find equation of parabola with three given points
        {
            double x1,x2,x3,y1,y2,y3, Det, Deta, Detb, Detc, a, b, c;
            QString qsResult, qsA, qsB, qsC, qsEquation;
            int iPoint1 = sscanf(KRestrictedLineInfo1->text().utf8(), "( %lf | %lf )", &x1, &y1);
            int iPoint2 = sscanf(KRestrictedLineInfo2->text().utf8(), "( %lf | %lf )", &x2, &y2);
            int iPoint3 = sscanf(KRestrictedLineInfo3->text().utf8(), "( %lf | %lf )", &x3, &y3);
            if (iPoint1 + iPoint2 + iPoint3 == 6)
            {
                Det = Determinant(x1*x1,x1, 1,x2*x2,x2,1,x3*x3,x3,1);
                if (Det == 0)
                {
                    qsResult = "<b>The function determined by the three given points <font color = red>isn't a parabola.</font></b>";
                }
                else
                {
                    Deta = Determinant(y1,x1, 1,y2,x2,1,y3,x3,1);
                    Detb = Determinant(x1*x1,y1, 1,x2*x2,y2,1,x3*x3,y3,1);
                    Detc = Determinant(x1*x1,x1, y1,x2*x2,x2,y2,x3*x3,x3,y3);
                    a = Deta / Det;
                    if (a == 0)
                    {
						qsResult = "<b>The function determined by the three given points <font color = red>isn't a parabola  but a line.</font></b>";
                    }
                    else
                    {
						b = Detb / Det;
						c = Detc / Det;
						qsA = qsA.arg(a);
						qsB = qsB.arg(b);
						qsC = qsC.arg(c);
						//Formatting the equation
						qsEquation = qsA + "*x <sup>2</sup> ";
						if (b == 0)
						{
							//Nothing to do
						}
						else if (b > 0)
						{
							qsEquation += "+ " + qsB + "*x";
						}
						else
						{
							qsEquation += qsB + "*x";
						}
						if (c == 0)
						{
							//Nothing to do
						}
						else if (c > 0)
						{
							qsEquation += "+ " + qsC;
						}
						else
						{
							qsEquation += qsC;
						}
						qsEquation.simplifyWhiteSpace();
						//End of Formatting
						qsResult = "The equation of the parabola, that runs through the three given points is:<br>";
						qsResult += "<b><i>" + qsEquation + "</i></b>.";
				    }
                }
                KTextBrowserResult->setText(qsResult);
            }
            else
            {
                KTextBrowserResult->setText(i18n("<font color=red size=+1><b>Incorrect format!</b></font> <p> Enter points like <b><i>(x<sub>1</sub>|x<sub>2</sub>)</i></b>"));
            }
            
            break;
        }
        
    case ScheitelAndPoint: //Find equation of parabola with Scheitel and one point
        {
            double x1,xs,y1,ys, Det, Deta, Detb, Detc, a, b, c;
            QString qsResult, qsA, qsB, qsC, qsEquation;
            int iPoint1 = sscanf(KRestrictedLineInfo2->text().utf8(), "( %lf | %lf )", &x1, &y1);
            int iPoints = sscanf(KRestrictedLineInfo1->text().utf8(), "( %lf | %lf )", &xs, &ys);
            if (iPoint1 + iPoints == 4)
            {
				Det = Determinant(x1*x1,x1, 1,xs*xs,xs,1,2*xs,1,0);
                if (Det == 0)
                {
                    qsResult = "<b>The function determined by the three given points <font color = red>isn't a parabola.</font></b>";
                    qsResult += "May be the vertex is identical to the second point?";
                }
                else
                {
                    Deta = Determinant(y1,x1, 1,ys,xs,1,0,1,0);
                    Detb = Determinant(x1*x1,y1, 1,xs*xs,ys,1,2*xs,0,0);
                    Detc = Determinant(x1*x1,x1, y1,xs*xs,xs,ys,2*xs,1,0);
                    a = Deta / Det;
                    if (a == 0)
                    {
						qsResult = "<b>The function determined by the three given points <font color = red>isn't a parabola  but a line.</font></b>";
                    }
                    else
                    {
						b = Detb / Det;
						c = Detc / Det;
						qsA = qsA.arg(a);
						qsB = qsB.arg(b);
						qsC = qsC.arg(c);
						//Formatting the equation
						qsEquation = qsA + "*x <sup>2</sup> ";
						if (b == 0)
						{
							//Nothing to do
						}
						else if (b > 0)
						{
							qsEquation += "+ " + qsB + "*x";
						}
						else
						{
							qsEquation += qsB + "*x";
						}
						if (c == 0)
						{
							//Nothing to do
						}
						else if (c > 0)
						{
							qsEquation += "+ " + qsC;
						}
						else
						{
							qsEquation += qsC;
						}
						qsEquation.simplifyWhiteSpace();
						//End of Formatting
						qsResult = "The equation of the parabola, that runs through the three given points is:<br>";
						qsResult += "<b><i>" + qsEquation + "</i></b>.";
				    }
                }
                KTextBrowserResult->setText(qsResult);
            }				
			else
			{
				KTextBrowserResult->setText(i18n("<font color=red size=+1><b>Incorrect format!</b></font> <p> Enter points like <b><i>(x<sub>1</sub>|x<sub>2</sub>)</i></b>"));
			}
            break;
        }
        
    case LineSection: //Find intersection point of parabola and line
        {
            double a, b, c, m, d, Dis, xs1, xs2, ys1,ys2;
            QString qsResult, qsYs1, qsXs1, qsYs2, qsXs2;
            
            int iParabola = sscanf(KRestrictedLineInfo1->text().utf8(), " %lf*x^2 %lf*x %lf )", &a, &b, &c);
            int iLine = sscanf(KRestrictedLineInfo2->text().utf8(), " %lf *x %lf )", &m, &d);
            if (iParabola + iLine == 5)
            {
				Dis = ((b - m)*(b - m)/(4*a*a)) - (( c- d)/a);
				if ( Dis < 0 )
				{
					//No intersection
					qsResult = "The given parabola and line <font color = red>do no intersect!</font>.";
				}
				else if (Dis == 0)
				{
					//one intersection point
					xs1 = -(b - m)/(2*a);
					ys1 = m*xs1+d;
					
					qsXs1 = qsXs1.arg(xs1);
					qsYs1 = qsYs1.arg(ys1);
					
					qsResult = "There is <b>one intersection-point</b> of the parabola and the line at <br>";
					qsResult += "<b><i>S(" + qsXs1 + "|" + qsYs1 + ")</i></b> .<br>";
					qsResult += "So the line is a <b>tangent</b> to the parabola.";
				}
				else
				{
					//two intersection points
					xs1 = -(b - m)/(2*a) + sqrt(Dis);
					xs2 = -(b - m)/(2*a) - sqrt(Dis);
					ys1 = m*xs1+d;
					ys2 = m*xs2+d;
					
					qsXs1 = qsXs1.arg(xs1);
					qsYs1 = qsYs1.arg(ys1);
					qsXs2 = qsXs2.arg(xs2);
					qsYs2 = qsYs2.arg(ys2);
					
					qsResult = "There is <b>two intersection-points</b> of the parabola and the line at <br>";
					qsResult += "<b><i>S<sub>1</sub>(" + qsXs1 + "|" + qsYs1 + ")</i></b> and <b><i>S<sub>2</sub>(" + qsXs2 + "|" + qsYs2 + ")</i></b>.<br>";
					qsResult += "So the line and the parabola do <b>intersect</b>.";
				}
				KTextBrowserResult->setText(qsResult);
			}
			else
			{
				qsResult = i18n("<font color=red size=+1><b>Incorrect format!</b></font> <p> Enter line like <b><i>m*x+b</i>)</b>");
				qsResult = i18n("and parabolas like <b><i>a*x^2+b*x+c</i></b><p>");
                qsResult += i18n("Even 1 and 0 as a factor or an addend is still needed.");
                KTextBrowserResult->setText(qsResult);
			}
            break;
        }
        
    case ParabolaSection: //Find intersection point of two parabolas
        {
            double a, b, c,d,e,f, Dis, xs1, xs2, ys1,ys2;
            QString qsResult, qsYs1, qsXs1, qsYs2, qsXs2;
            
            int iParabola1 = sscanf(KRestrictedLineInfo1->text().utf8(), " %lf*x^2 %lf*x %lf )", &a, &b, &c);
            int iParabola2 = sscanf(KRestrictedLineInfo2->text().utf8(), " %lf*x^2 %lf*x %lf )", &d, &e, &f);
            if (iParabola1 + iParabola2 == 6)
            {
				Dis = (b- e)*(b-e)/(2*(a-d)*(a-d))-((c-f)/(a-d));
				if ( Dis < 0 )
				{
					//No intersection
					qsResult = "The two given parabolas <font color = red>do no intersect!</font>.";
				}
				else if (Dis == 0)
				{
					//one intersection point
					xs1 = - (b - e)/(2*(a-d));
					ys1 = a*xs1*xs1+b*xs1+c;
					
					qsXs1 = qsXs1.arg(xs1);
					qsYs1 = qsYs1.arg(ys1);
					
					qsResult = "There is <b>one intersection-point</b> of the two parabolas at<br>";
					qsResult += "<b><i>S(" + qsXs1 + "|" + qsYs1 + ")</i></b> .<br>";
					qsResult += "So the two parabolas are <b>tangent</b> to each other at the intersection point.";
				}
				else
				{
					//two intersection points
					xs1 = - (b - e)/(2*(a-d)) + sqrt(Dis);
					xs2 = - (b - e)/(2*(a-d)) - sqrt(Dis);
					ys1 = a*xs1*xs1+b*xs1+c;
					ys2 = a*xs2*xs2+b*xs2+c;
					
					qsXs1 = qsXs1.arg(xs1);
					qsYs1 = qsYs1.arg(ys1);
					qsXs2 = qsXs2.arg(xs2);
					qsYs2 = qsYs2.arg(ys2);
					
					qsResult = "There is <b>two intersection-points</b> of the parabola and the line at <br>";
					qsResult += "<b><i>S<sub>1</sub>(" + qsXs1 + "|" + qsYs1 + ")</i></b> and <b><i>S<sub>2</sub>(" + qsXs2 + "|" + qsYs2 + ")</i></b>.<br>";
					qsResult += "So the line and the parabola do <b>intersect</b>.";
				}
				KTextBrowserResult->setText(qsResult);
			}
			else
			{
				qsResult = i18n("<font color=red size=+1><b>Incorrect format!</b></font> <p> Enter parabolas like <b><i>a*x^2+b*x+c</i></b><p>");
                qsResult += i18n("Even 1 and 0 as a factor or an addend is still needed.");
                KTextBrowserResult->setText(qsResult);
			}
            break;
        }
    }
}

void Parabolas::slotClear()
{
    KTextBrowserResult->setText("");
    KRestrictedLineInfo1->setText("");
    KRestrictedLineInfo2->setText("");
    KRestrictedLineInfo3->setText("");
    /*KPushButtonCalculate->setEnabled(false); 
    KPushButtonClear->setEnabled(false); */
}

void Parabolas::slotCheckBoxes(const QString &qsText)
{}

double Parabolas::Determinant(double d11,double d12, double d13, double d21, double d22, double d23, double d31, double d32, double d33)
{
    double Det = d11*d22*d33+d12*d23*d31+d13*d21*d32-d31*d22*d13-d32*d23*d11-d33*d21*d12;
	return Det; 
}
