
/* Addresses.c: email address, aliasing, etc.
 *
 * This file is part of Aileron, a WINGs email client. 
 *
 *  Copyright (c) 1999 - 2001  Nwanua Elumeze
 *
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "Aileron.h"

struct  {
  WMWindow  *window;
  WMTextField *namet;
  WMText     *addresst;
  WMList    *addressl;
  WMLabel    *facel;
  
  unsigned short textChanged:1;
  unsigned short RESERVED:16;
  
} AddressesPanel;


static void
closePanel(WMWidget *self, void *client)
{
  WMUnmapWidget(AddressesPanel.window);
}


static void
addCB(WMWidget *w, void *client)
{
  WMListItem *item;
  char *name = WMGetTextFieldText(AddressesPanel.namet);
  
  if(!name || strlen(name) < 1)
    return;

  item = WMAddListItem(AddressesPanel.addressl, name);
  item->clientData = WMGetTextStream(AddressesPanel.addresst);
  WMSortListItems(AddressesPanel.addressl);
  WMSetTextFieldText(AddressesPanel.namet, NULL);
}
  
static void
selectListItem(int i, char *text)
{
  WMSelectListItem(AddressesPanel.addressl, i);
  WMAppendTextStream(AddressesPanel.addresst, NULL);
  WMAppendTextStream(AddressesPanel.addresst, text);
  WMSetListPosition(AddressesPanel.addressl, i);
}

static void
removeCB(WMWidget *w, void *client)
{
  WMRemoveListItem(AddressesPanel.addressl,
    WMGetListSelectedItemRow(AddressesPanel.addressl));
  WMAppendTextStream(AddressesPanel.addresst, NULL);
}

static void
changeCB(WMWidget *w, void *client)
{
  WMListItem *item = WMGetListSelectedItem(AddressesPanel.addressl);
  if(item) {
    item->text = WMGetTextFieldText(AddressesPanel.namet);
    WMSortListItems(AddressesPanel.addressl);
    WMSetListUserDrawItemHeight(AddressesPanel.addressl, 
      WMGetListItemHeight(AddressesPanel.addressl));
    if(item->clientData)
      free(item->clientData);
    item->clientData = 
      WMGetTextStream(AddressesPanel.addresst);
  }
}


static void
findItem(XEvent *event, void *data)
{
  WMListItem *item;
  int len, nrows, i, result=0;
  char *text;


  text = WMGetTextFieldText(AddressesPanel.namet);
  if(!text || strlen(text)<1)
    return;

  nrows = WMGetListNumberOfRows(AddressesPanel.addressl);
  len = strlen(text);
  
  for(i=0; i<nrows; i++) {
    item = WMGetListItem(AddressesPanel.addressl, i);
    if(item && item->text) 
      if((result = !strncmp(item->text, text, len)))
        break;
  }
  

//strncmp
  if(result) {
    selectListItem(i, item->clientData);
  }

}

static void
ccCB(WMWidget *w, void *client)
{
  WMListItem *item = WMGetListSelectedItem(AddressesPanel.addressl);
  if(item) 
    AppendCC(Aileron.composer, item->text);
}


static void
toCB(WMWidget *w, void *client)
{
  WMListItem *item = WMGetListSelectedItem(AddressesPanel.addressl);
  if(item) 
    AppendTo(Aileron.composer, item->text);
}

static void
getAddress(WMWidget *list, void *data)
{
  WMListItem *item = WMGetListSelectedItem(AddressesPanel.addressl);
  
  if(!item)
    return;

  WMSetTextFieldText(AddressesPanel.namet, item->text);
  WMAppendTextStream(AddressesPanel.addresst, NULL);
  WMAppendTextStream(AddressesPanel.addresst, (char *)
    item->clientData);
  WMThawText(AddressesPanel.addresst);
}


char *
GetCharFromAddress(ADDRESS *addr)
{   
  int   len;
  char *str = NULL, *tmp = NULL; 
  Bool first=True;
  
  while(addr) {
    if(addr->mailbox &&  addr->host) {
      len = strlen(addr->mailbox)+strlen(addr->host)+4;
      tmp = (char *)wmalloc(len);
      memset(tmp, 0, len);
      sprintf(tmp, "%.256s@%.256s", addr->mailbox, addr->host);
      if(first) {
        str = wstrdup(tmp);
        first = False;
      } else {
        str = wstrappend(str, ", ");
        str = wstrappend(str, tmp);
      }   
    }   
    
    addr = addr->next;
       
  }
  
  return str;
}   

static void
fillAddressList(WMList *l)
{
  WMListItem *item;
  int i, n;
  char *val;
  WMPropList *name = NULL, *users = NULL, *addresses = NULL;
  WMPropList *keys;
  
  WMClearList(l);

  addresses = WMGetUDObjectForKey(Aileron.defaultsDB, "Addresses");
  if(!addresses || !WMIsPLDictionary(addresses)) 
    return;

  keys = WMGetPLDictionaryKeys(addresses);
  n = WMGetPropListItemCount(keys);
  
  for(i=0; i<n; i++) {

    name = WMGetFromPLArray(keys, i);
    if(name) { 
      val = wstrdup(WMGetFromPLString(name));
      if(!val)
        continue;

      item = WMAddListItem(AddressesPanel.addressl, val);

      users = WMGetFromPLDictionary(addresses, name);
      if(users)
        item->clientData = wstrdup(WMGetFromPLString(users));
      else 
        item->clientData = NULL;
    }
  }
  WMSortListItems(AddressesPanel.addressl);
}
  

  
  
void
runAddressesPanel(void)
{
  unsigned w=400, h=232;
  WMLabel *l;
  WMButton *b;
  
  AddressesPanel.window = WMCreateWindowWithStyle(Aileron.screen,
    "Aileron Addresses", 
    WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
  WMSetWindowTitle(AddressesPanel.window, "Aileron: Addresses");
  WMSetWindowMinSize(AddressesPanel.window, w, h);
  WMSetWindowMaxSize(AddressesPanel.window, w, h);
  WMResizeWidget(AddressesPanel.window, w, h);    
  
  l = NewLabel(AddressesPanel.window, "Names", 10, 10, 140, 20);
  WMSetLabelRelief(l, WRSunken);
  WMSetLabelTextAlignment(l, WACenter);
  WMSetLabelFont(l, WMBoldSystemFontOfSize(Aileron.screen, 12));
  WMSetLabelTextColor(l, WMWhiteColor(Aileron.screen));
  WMSetWidgetBackgroundColor(l, WMDarkGrayColor(Aileron.screen));


  l = NewLabel(AddressesPanel.window, "Addresses", 153, 10, 237, 20);
  WMSetLabelRelief(l, WRSunken);
  WMSetLabelTextAlignment(l, WACenter);
  WMSetLabelFont(l, WMBoldSystemFontOfSize(Aileron.screen, 12));
  WMSetLabelTextColor(l, WMWhiteColor(Aileron.screen));
  WMSetWidgetBackgroundColor(l, WMDarkGrayColor(Aileron.screen));

  AddressesPanel.addressl = WMCreateList(AddressesPanel.window);
  WMResizeWidget(AddressesPanel.addressl, 140, 140);
  WMMoveWidget(AddressesPanel.addressl, 10, 32);
  WMSetListAction(AddressesPanel.addressl, getAddress, NULL);
  
  AddressesPanel.addresst = WMCreateText(AddressesPanel.window);
  WMSetTextIgnoresNewline(AddressesPanel.addresst, True);
  WMResizeWidget(AddressesPanel.addresst, 237, 140);
  WMMoveWidget(AddressesPanel.addresst, 153, 32);
  WMSetTextHasVerticalScroller(AddressesPanel.addresst, True);
  WMSetTextRelief(AddressesPanel.addresst, WRSunken);
#if 0
  WMCreateEventHandler(WMWidgetView(AddressesPanel.addresst),
    LeaveWindowMask | KeyPressMask, changeUserList, NULL);
#endif
  
  
  l = NewLabel(AddressesPanel.window, "Name:", 6, 176, 42, 20);
  AddressesPanel.namet = NewTextField(AddressesPanel.window, 
    NULL, 48, 176, 342, 20);
  WMCreateEventHandler(WMWidgetView(AddressesPanel.namet),
    KeyPressMask, findItem, NULL);
  WMSetBalloonTextForView("To search for a name in the list, \n"
    "hit the \"Return/Enter\" key after typing enough text here.",
    WMWidgetView(AddressesPanel.namet));

    
  {
    char *t[] = {"Remove", "Change", "Add", "cc:", "To:"};
    int x=48, i;
    void *F[] = {removeCB, changeCB, addCB, ccCB, toCB};

    for(i=0; i<5; i++) {
      b = WMCreateCommandButton(AddressesPanel.window);
      WMSetButtonText(b, t[i]);
        WMMoveWidget(b, x, 200);
      WMResizeWidget(b, 62, 24);
      x += 70;
      WMSetButtonAction(b, F[i], NULL);
    }
      
  }


  WMSetWindowCloseAction(AddressesPanel.window, closePanel, NULL);
  
  
  WMRealizeWidget(AddressesPanel.window);
  WMMapSubwidgets(AddressesPanel.window); 
  WMAppAddWindow(Aileron.appContext, WMWidgetXID(AddressesPanel.window));
  
  WMHashInsert(Aileron.windowTable, "_ADDRESSES_PANEL_",
    &AddressesPanel);
    

  fillAddressList(AddressesPanel.addressl);

  Aileron.addressesCreated = True;
  AddressesPanel.textChanged = False;
  
}

void 
SaveAddresses(void)
{
  WMListItem *item;
  int i, n;
  WMPropList *name = NULL, *users = NULL, *addresses = NULL;

  if(!Aileron.addressesCreated) 
    return;
  
  n = WMGetListNumberOfRows(AddressesPanel.addressl);
  for(i=0; i<n; i++) {
    item = WMGetListItem(AddressesPanel.addressl, i);

    if(item->text && item->clientData) { 
      name = WMCreatePLString(wstrdup(item->text));
      users = WMCreatePLString(wstrdup(item->clientData));
    
      if(!addresses) {
        addresses = WMCreatePLDictionary(
          name, users, NULL);
      } else {
        WMPutInPLDictionary(addresses, name, users);
      }
      WMReleasePropList(name);
      WMReleasePropList(users);

    }
  }

  if(addresses) { 
    WMSetUDObjectForKey(Aileron.defaultsDB, addresses, "Addresses");
    WMReleasePropList(addresses);
  }
}
        


  
char *ExpandAddress(char *name)
{
  WMListItem *item;
  int r;

  if(!name)
    return NULL;

  if(!Aileron.addressesCreated) 
    runAddressesPanel();

  r = WMFindRowOfListItemWithTitle(AddressesPanel.addressl, name);
  item = WMGetListItem(AddressesPanel.addressl, r);
  
  if(item && item->clientData) 
    return wstrdup(item->clientData);
  else 
    return wstrdup(name);
}


void
AddAddress(void *vmbox)
{
  ENVELOPE *env;
  MAILSTREAM *stream;
  unsigned long msgno;
  char *address = NULL, sender[MAILTMPLEN];
  int i;

  if(!vmbox)
    return;

  if(!Aileron.addressesCreated) 
    runAddressesPanel();

  stream = GetMailBoxStream(vmbox);
  msgno = GetMailBoxSelectedMessage(vmbox);

  if(!stream || msgno < 1) {
    return;
  }
  

  env = mail_fetchenvelope(stream, msgno);
  if(!env)
    return;

  mail_fetchfrom(sender, stream, msgno, (long)MAILTMPLEN-1);
  if ((i = strlen(sender)) < 1)
    return;
 
  do --i; while(i>0 && sender[i] == ' ');
  sender[i+1] = 0;

  
  address = GetCharFromAddress(env->from);

  WMSetTextFieldText(AddressesPanel.namet, sender);
  WMAppendTextStream(AddressesPanel.addresst, NULL);
  WMAppendTextStream(AddressesPanel.addresst, address);
  WMThawText(AddressesPanel.addresst);
  addCB(NULL, NULL);

}

void
RunAddressesPanel(void)
{

  if(Aileron.addressesCreated) {
    XRaiseWindow(Aileron.display,
      WMWidgetXID(AddressesPanel.window));
    WMMapWidget(AddressesPanel.window);
    return;
  }   

  runAddressesPanel();
  WMMapWidget(AddressesPanel.window);
}

