// Ascending Sort the selection or whole document and zap the duplicate.
// The seperator can be any character(s), the default is "\r", ESC sequence is supported.
// Default value - StrAsc
// "DESC"	 - StrDesc
// "NUM"	 - NumAsc
// "NUMDESC"	 - NumDesc
// "ZAP"	 - StrAsc and then Remove duplicate
// "DESCZAP"	 - StrDesc and then Remove duplicate
// "NUMZAP"	 - NumAsc and then Remove duplicate
// "NUMDESCZAP"	 - NumDesc and then Remove duplicate

try
{
  var hMainWnd=AkelPad.GetMainWnd();
}
catch (oError)
{
  WScript.Quit();
}

var pScriptName=WScript.ScriptName;
var oSys=AkelPad.SystemFunction();

var pSelText = GetTxt();
var pSeperator=AkelPad.InputBox(hMainWnd, pScriptName, "Seperator(ESC sequence is supported):", "\\r");

if (typeof pSeperator=="undefined") WScript.Quit();

pSeperator = Escseq(pSeperator);

var pLinesArray=pSelText.split("\r");
if (pSeperator=="\r")
{
  SortArray(pLinesArray);
  pSelText=pLinesArray.join("\r");
}
else
{
  for (i=0; i<pLinesArray.length; ++i)
  {
    var pLineArray = pLinesArray[i].split(pSeperator);
    SortArray(pLineArray);
    pLinesArray[i]=pLineArray.join(pSeperator);
  }
  pSelText=pLinesArray.join("\r");
}
AkelPad.ReplaceSel(pSelText);


function GetTxt(bCompleteLine)
{
  var hWndEdit =AkelPad.GetEditWnd();
  var nSelStart=AkelPad.GetSelStart();
  var nSelEnd  =AkelPad.GetSelEnd();

  if (nSelStart == nSelEnd)
  {
    var lpPoint = AkelPad.MemAlloc(8 /*sizeof(POINT)*/, true);

    if(!lpPoint)
      return "";

    setRedraw(hWndEdit, false);
    AkelPad.SendMessage(hWndEdit, 1245 /*EM_GETSCROLLPOS*/, 0, lpPoint);
    AkelPad.SetSel(0, -1);
    //    AkelPad.SetSel(nSelStart, nSelEnd);
    AkelPad.SendMessage(hWndEdit, 1246 /*EM_SETSCROLLPOS*/, 0, lpPoint);
    AkelPad.MemFree(lpPoint, true);
    setRedraw(hWndEdit, true);
  }
  else
  {
    if(!AkelPad.SendMessage(hWndEdit, 3127 /*AEM_GETCOLUMNSEL*/, 0, 0) && bCompleteLine)
    {
      SelCompliteLine(hWndEdit, nSelStart, nSelEnd);
      nSelStart=AkelPad.GetSelStart();
      nSelEnd  =AkelPad.GetSelEnd();
    }
  }
  return AkelPad.GetSelText(1 /*\r*/);
}
function setRedraw(hWnd, bRedraw)
{
  AkelPad.SendMessage(hWnd, 11 /*WM_SETREDRAW*/, bRedraw, 0);
  bRedraw && oSys.Call("user32::InvalidateRect", hWnd, 0, true);
}

function SelCompliteLine(hWnd, nMinSel, nMaxSel)
{
  var nMinLine;
  var nMaxLine;
  var nMinLineIndex;
  var nMaxLineIndex;
  var nMaxLineLength;
  if (nMinSel < nMaxSel)
  {
    nMinLine=AkelPad.SendMessage(hWnd, 1078 /*EM_EXLINEFROMCHAR*/, 0, nMinSel);
    nMaxLine=AkelPad.SendMessage(hWnd, 1078 /*EM_EXLINEFROMCHAR*/, 0, nMaxSel);
    nMinLineIndex=AkelPad.SendMessage(hWnd, 187 /*EM_LINEINDEX*/, nMinLine, 0);
    nMaxLineIndex=AkelPad.SendMessage(hWnd, 187 /*EM_LINEINDEX*/, nMaxLine, 0);
    nMaxLineLength=AkelPad.SendMessage(hWnd, 193 /*EM_LINELENGTH*/, nMaxSel, 0);
    if (nMaxLineIndex == nMaxSel) --nMaxLine;
    else if (nMaxLineLength) nMaxSel=nMaxLineIndex + nMaxLineLength + 1;
    nMinSel=nMinLineIndex;
    AkelPad.SetSel(nMinSel, nMaxSel);
    return nMaxLine - nMinLine + 1;
  }
  return 0;
}

function Escseq(EscStr)
{
  //Esc-sequences
  EscStr=EscStr.replace(/\\\\/g, "\0");
  if (EscStr.search(/\\[^rnt]/g) !=-1)
  {
    AkelPad.MessageBox(hWndDlg, pSyntaxError, pScriptName, 16 /*MB_ICONERROR*/);
    return false;
  }
  EscStr=EscStr.replace(/(?:\\r\\n|\\r|\\n)/g, "\r");
  EscStr=EscStr.replace(/\\t/g, "\t");
  EscStr=EscStr.replace(/\0/g, "\\");
  return EscStr;
}

function SortArray(pLineArray)
{
  var bDesc1 = 0; // = 1 if key 1 descending
  var bCase = 0; // = 1 Match Case

  if (WScript.Arguments.length)
  {
    var pArg=WScript.Arguments(0);
    pArg=pArg.toUpperCase();

    if (pArg=="DESC" || pArg=="DESCZAP" || pArg== "NUMDESC" || pArg=="NUMDESCZAP") bDesc1 = 1;
    if (pArg=="NUM" || pArg== "NUMZAP" || pArg== "NUMDESC" || pArg=="NUMDESCZAP")
    {
      pLineArray.sort(function(a, b)
      {
        if (Number(a) < Number(b)) return (bDesc1 ?  1 : -1);
        else if (Number(a) > Number(b)) return (bDesc1 ? -1 :  1);
        else return 0;
      });
    }
    else
    {
      if (bCase)
      {
        pLineArray.sort(function(a, b)
        {
          if (a < b) return (bDesc1 ?  1 : -1);
          else if (a > b) return (bDesc1 ? -1 :  1);
          else return 0;
        });
      }
      else
      {
        pLineArray.sort(function(a, b)
        {
          if (a.toUpperCase() < b.toUpperCase()) return (bDesc1 ?  1 : -1);
          else if (a.toUpperCase() > b.toUpperCase()) return (bDesc1 ? -1 :  1);
          else return 0;
        });
      }
    }
    if (pArg=="ZAP" || pArg== "NUMZAP" || pArg== "DESCZAP" || pArg=="NUMDESCZAP")
    {
      // zap the duplicate
      for (i=0; i < pLineArray.length; ++i)
      {
        if (pLineArray[i]==pLineArray[i+1])
        {
          pLineArray.splice(i,1);
          --i;
        }
      }
    }
  }
  else
  {
    if (bCase)
    {
      pLineArray.sort(function(a, b)
      {
        if (a < b) return (bDesc1 ?  1 : -1);
        else if (a > b) return (bDesc1 ? -1 :  1);
        else return 0;
      });
    }
    else
    {
      pLineArray.sort(function(a, b)
      {
        if (a.toUpperCase() < b.toUpperCase()) return (bDesc1 ?  1 : -1);
        else if (a.toUpperCase() > b.toUpperCase()) return (bDesc1 ? -1 :  1);
        else return 0;
      });
    }
  }
}