/* **************************************************************************
  This file is part of KBabel

  Copyright (C) 2001 by Matthias Kiefer <kiefer@kde.org>
  Diff algorithm by Wolfram Diestel <wolfram@steloj.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.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

************************************************************************** */

#include "diff.h"

#include <kdebug.h>

QString Diff::charDiff(QString s1, QString s2)
{
    int n = 3;
    s1+="xxx";
    s2+="xxx";
    
    int pos1=0;
    int pos2=0;
    int len1 = s1.length();
    int len2 = s2.length();
    QString resultstr;
    bool found = true;
    bool swap = false;
    while (found && pos1+n < len1 && pos2+n < len2) 
    {
        // while strings are equal, increase positions
        int len = 0;
        while (pos1+len < len1 && pos2+len < len2 &&
                (s1[pos1+len] == s2[pos2+len]))
        {
           len++;
        }
         
        // write first result
        resultstr += s1.mid(pos1,len);
        pos1 += len;
        pos2 += len;

        // If strings are not equal try to find equal substrings of
        // length n. For this increase positions alternating like
        // 0 1, 1 0, 0 2, 1 1, 2 0, 0 3, 1 2, 2 1, 3 0 etc.

        int x = 1;
        found = false;

        // If one position is already at the end stop processing
        if (pos1+n >= len1 || pos2+n >= len2) 
        {
            break;
        }


        // evtl. exchange
        if (len2 - pos2 < len1 - pos1) 
        {
            swap=true;
            
            int pos = pos1; 
            pos1 = pos2; 
            pos2 = pos;
            
            QString s = s1; 
            s1 = s2; 
            s2 = s;
            
            int len = len1; 
            len1 = len2; 
            len2 = len;
         }

         while( !found && (pos1+x < len1 || pos2+x <len2)) 
         {
            int p1;
            int p2;
            for(p1 = 0, p2 = x; p1 <= x; p1++, p2--) 
            {
                 if( pos1+p1+n >= len1 || pos2+p2+n >= len2)
                     break;

                 if(s1.mid(pos1+p1,n) == s2.mid(pos2+p2,n))
                 {
                    found = true;

                    // evtl. exchange back
                    if(swap) 
                    {
                         int pos = pos1; 
                         pos1 = pos2; 
                         pos2 = pos;
                         
                         QString s = s1;
                         s1 = s2;
                         s2 = s;
                         
                         int len = len1;
                         len1 = len2;
                         len2 = len;
                         
                         int p = p1;
                         p1 = p2;
                         p2 = p;
                         
                         swap=false;
                    }


                    // write current result 
                    if (p1 > 0) 
                    {
                         resultstr += "<KBABELDEL>";
                         resultstr += s1.mid(pos1,p1);
                         resultstr += "</KBABELDEL>";
                         pos1 += p1;
                    }

                    if (p2 > 0 ) 
                    {
                         resultstr += "<KBABELADD>";
                         resultstr += s2.mid(pos2,p2);
                         resultstr += "</KBABELADD>";
                         pos2 += p2;
                    }

                    break;
                 }
            }
            
            x++;
            
         }

    }

    bool removed=false;
 
    // evtl. exchange back
    if(swap) 
    {
         int pos = pos1; 
         pos1 = pos2; 
         pos2 = pos;
         
         QString s = s1;
         s1 = s2;
         s2 = s;
         
         int len = len1;
         len1 = len2;
         len2 = len;
         
         swap=false;
    }
   
    // if there is a rest, add it
    if(pos1+n < len1) 
    {
         resultstr += "<KBABELDEL>";
         resultstr += s1.mid(pos1,len1-pos1-n);
         resultstr += "</KBABELDEL>";
         removed=true;
    }

    if(pos2+n < len2) 
    {
         resultstr += "<KBABELADD>";
         resultstr += s2.mid(pos2,len2-pos2-n);
         resultstr += "</KBABELADD>";
         removed=true;
    }

    if( !removed ) 
    {
        resultstr.truncate( resultstr.length()-3 );
    }

    return resultstr;
}
