/*
* Copyright (c) 2003-2014 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

#include "PasswordSafe.h"
#include "DboxMain.h"
#include "AddEdit_PropertySheet.h"
#include "GeneralMsgBox.h"

#include "core/ItemData.h"
#include "core/PWSprefs.h"

using pws_os::CUUID;

IMPLEMENT_DYNAMIC(CAddEdit_PropertySheet, CPWPropertySheet)

CAddEdit_PropertySheet::CAddEdit_PropertySheet(UINT nID, CWnd* pParent,
                                               PWScore *pcore,
                                               CItemData *pci_original, CItemData *pci,
                                               const bool bLongPPs,
                                               const StringX currentDB)
  : CPWPropertySheet(nID, pParent, bLongPPs), m_bIsModified(false), m_bChanged(false),
  m_bNotesChanged(false), m_bSymbolsChanged(false)
{
  m_AEMD.bLongPPs = bLongPPs;
  m_AEMD.uicaller = nID;

  ASSERT(pParent != NULL);
  ASSERT(pcore != NULL);
  ASSERT(pci != NULL);

  m_AEMD.pcore = pcore;
  m_AEMD.pci_original = pci_original;
  m_AEMD.pci = pci;

  m_AEMD.currentDB = currentDB;

  PWSprefs *prefs = PWSprefs::GetInstance();

  m_AEMD.default_pwp = prefs->GetDefaultPolicy();
  m_AEMD.default_symbols = prefs->GetPref(PWSprefs::DefaultSymbols);

  // Set up data used by all Property Pages, as appropriate
  if (m_AEMD.uicaller == IDS_ADDENTRY) {
    // Basic initialisation
    m_AEMD.group = L"";
    m_AEMD.title = L"";
    m_AEMD.username = L"";
    m_AEMD.realpassword = L"";
    m_AEMD.realnotes = m_AEMD.originalrealnotesTRC = L"";
    m_AEMD.URL = L"";
    m_AEMD.email = L"";
    m_AEMD.symbols = m_AEMD.oldsymbols = L"";

    // Entry type initialisation
    m_AEMD.original_entrytype = CItemData::ET_NORMAL;

    // Additional initialisation
    m_AEMD.autotype = L"";
    m_AEMD.runcommand = L"";
    m_AEMD.oldDCA = m_AEMD.DCA = m_AEMD.oldShiftDCA = m_AEMD.ShiftDCA = -1;

    // Date & Time initialisation
    m_AEMD.locCTime.LoadString(IDS_NA);
    m_AEMD.locXTime = m_AEMD.locATime = m_AEMD.locRMTime = m_AEMD.locPMTime =
          m_AEMD.oldlocXTime = m_AEMD.locCTime;
    m_AEMD.tttXTime = m_AEMD.tttCPMTime = (time_t)0;
    m_AEMD.oldXTimeInt = m_AEMD.XTimeInt = 0;

    // PWHistory initialisation
    m_AEMD.SavePWHistory = m_AEMD.oldSavePWHistory =
            PWSprefs::GetInstance()->GetPref(PWSprefs::SavePasswordHistory) ? TRUE : FALSE;
    m_AEMD.MaxPWHistory = m_AEMD.oldMaxPWHistory =
            PWSprefs::GetInstance()->GetPref(PWSprefs::NumPWHistoryDefault);
    m_AEMD.NumPWHistory = m_AEMD.oldNumPWHistory = 0;

    // PWPolicy fields
    m_AEMD.pwp = m_AEMD.oldpwp = m_AEMD.default_pwp;
    m_AEMD.ipolicy = m_AEMD.oldipolicy = DEFAULT_POLICY;
    m_AEMD.iownsymbols = m_AEMD.ioldownsymbols = DEFAULT_SYMBOLS;
    m_AEMD.symbols = L"";
    m_AEMD.policyname = m_AEMD.oldpolicyname = L"";

    // Protected
    m_AEMD.ucprotected = 0;
    
    // Entry Keyboard shortcut
    m_AEMD.oldKBShortcut = m_AEMD.KBShortcut = 0;
  } else {
    SetupInitialValues();
  }
  // Only now allocate the PropertyPages - after all data there
  // to be used by their c'tors
  m_pp_basic      = new CAddEdit_Basic(this, &m_AEMD);
  m_pp_additional = new CAddEdit_Additional(this, &m_AEMD);
  m_pp_datetimes  = new CAddEdit_DateTimes(this, &m_AEMD);
  m_pp_pwpolicy   = new CAddEdit_PasswordPolicy(this, &m_AEMD);

  AddPage(m_pp_basic);
  AddPage(m_pp_additional);
  AddPage(m_pp_datetimes);
  AddPage(m_pp_pwpolicy);
}

CAddEdit_PropertySheet::~CAddEdit_PropertySheet()
{
  delete m_pp_basic;
  delete m_pp_additional;
  delete m_pp_datetimes;
  delete m_pp_pwpolicy;
}

BEGIN_MESSAGE_MAP(CAddEdit_PropertySheet, CPWPropertySheet)
  //{{AFX_MSG_MAP(CAddEdit_PropertySheet)
  ON_WM_SYSCOMMAND()
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CAddEdit_PropertySheet::OnSysCommand(UINT nID, LPARAM lParam)
{
  const UINT nSysID = nID & 0xFFF0;
  if (nSysID == SC_CLOSE &&
      (m_AEMD.uicaller == IDS_VIEWENTRY ||
      (m_AEMD.uicaller == IDS_EDITENTRY &&  m_AEMD.ucprotected != 0))) {
    EndDialog(IDCANCEL);
    return;
  }
  CPWPropertySheet::OnSysCommand(nID, lParam);
}

BOOL CAddEdit_PropertySheet::OnInitDialog()
{
  CPWPropertySheet::OnInitDialog();

  // Change the Window title for Edit/View
  switch (m_AEMD.uicaller) {
    case IDS_ADDENTRY:
      break;
    case IDS_VIEWENTRY:
    case IDS_EDITENTRY:
      {
        CString cs_title;
      StringX sx_group(L""), sx_title, sx_user(L"");
      if (!m_AEMD.pci->IsGroupEmpty())
        sx_group = m_AEMD.pci->GetGroup();
      sx_title = m_AEMD.pci->GetTitle();
      if (!m_AEMD.pci->IsUserEmpty())
        sx_user = m_AEMD.pci->GetUser();

      // Set up and pass Propertysheet caption showing entry being edited/viewed
      // If entry is protected, set to 'View' even if DB is in R/W mode
      cs_title.Format(m_AEMD.ucprotected != 0 ? IDS_PROTECTEDENTRY : m_AEMD.uicaller,
                      sx_group.c_str(), sx_title.c_str(), sx_user.c_str());
      SetWindowText(cs_title);
      break;
      }
    default:
      ASSERT(0);
  }

  // Change the Control ID for the Apply button so that we get it
  switch (m_AEMD.uicaller) {
    case IDS_ADDENTRY:
      break;
    case IDS_VIEWENTRY:
      GetDlgItem(IDCANCEL)->EnableWindow(FALSE);
      GetDlgItem(IDCANCEL)->ShowWindow(SW_HIDE);
      break;
    case IDS_EDITENTRY:
      GetDlgItem(ID_APPLY_NOW)->EnableWindow(m_bChanged || m_bSymbolsChanged ? TRUE : FALSE);
      break;
  }
  return TRUE;
}

void CAddEdit_PropertySheet::SetSymbolsChanged(const bool bSymbolsChanged)
{
  m_bSymbolsChanged = bSymbolsChanged;
  bool bChanged = m_bChanged || m_bSymbolsChanged;

  GetDlgItem(IDOK)->EnableWindow(bChanged ? TRUE : FALSE);
  if (m_AEMD.uicaller == IDS_EDITENTRY)
    GetDlgItem(ID_APPLY_NOW)->EnableWindow(bChanged ? TRUE : FALSE);
}

void CAddEdit_PropertySheet::SetChanged(const bool bChanged)
{
  if (m_bChanged != bChanged) {
    if (m_AEMD.uicaller == IDS_EDITENTRY)
      GetDlgItem(ID_APPLY_NOW)->EnableWindow(bChanged ? TRUE : FALSE);
    switch (m_AEMD.uicaller) {
    case IDS_ADDENTRY:
      break;
    case IDS_VIEWENTRY:
    case IDS_EDITENTRY:
      {
        CString cs_title;
        StringX sx_group(L""), sx_title, sx_user(L"");
        if (!m_AEMD.pci->IsGroupEmpty())
          sx_group = m_AEMD.pci->GetGroup();
        sx_title = m_AEMD.pci->GetTitle();
        if (!m_AEMD.pci->IsUserEmpty())
          sx_user = m_AEMD.pci->GetUser();

        // Set up and pass Propertysheet caption showing entry being edited/viewed
        // If entry is protected, set to 'View' even if DB is in R/W mode
        cs_title.Format(m_AEMD.ucprotected != 0 ? IDS_PROTECTEDENTRY : m_AEMD.uicaller,
                        sx_group.c_str(), sx_title.c_str(), sx_user.c_str());

        const CString asterisk = L"*";
        if (bChanged)
          cs_title += asterisk;
        else
          cs_title.TrimRight(asterisk[0]);

        SetWindowText(cs_title);
        break;
      }
    default:
      ASSERT(0);
    }
    m_bChanged = bChanged;
  }
}

BOOL CAddEdit_PropertySheet::OnCommand(WPARAM wParam, LPARAM lParam)
{
  // There is no OnOK for classes derived from CPropertySheet,
  // so we make our own!
  const int iCID = LOWORD(wParam);
  if (HIWORD(wParam) == BN_CLICKED && (iCID == IDOK || iCID == ID_APPLY_NOW)) {
    // Don't care what user has done if entry is protected or DB R-O.
    if (m_AEMD.ucprotected != 0 || m_AEMD.uicaller == IDS_VIEWENTRY)
      CPWPropertySheet::EndDialog(IDOK);

    // First send a message to all loaded pages using base class function.
    // We want them all to update their variables in the Master Data area.
    // And call OnApply() rather than the default OnOK processing
    // Note: This message is only sent to PropertyPages that have been
    // loaded - i.e. the user has selected to view them, since obviously
    // the user would not have changed their values if not displayed. Duh!
    if (SendMessage(PSM_QUERYSIBLINGS,
                (WPARAM)CPWPropertyPage::PP_UPDATE_VARIABLES, 0L) != 0) {
      return TRUE;
    }

    time_t t;
    bool bIsPSWDModified;
    short iDCA, iShiftDCA;

    switch (m_AEMD.uicaller) {
      case IDS_EDITENTRY:
        // Make as View entry if protected
        if (m_AEMD.ucprotected != 0)
          break;

        m_AEMD.pci->GetDCA(iDCA);
        m_AEMD.pci->GetShiftDCA(iShiftDCA);
        // Check if modified
        m_bIsModified = (m_AEMD.group       != m_AEMD.pci->GetGroup()      ||
                         m_AEMD.title       != m_AEMD.pci->GetTitle()      ||
                         m_AEMD.username    != m_AEMD.pci->GetUser()       ||
                         m_AEMD.realnotes   != m_AEMD.originalrealnotesTRC ||
                         m_AEMD.URL         != m_AEMD.pci->GetURL()        ||
                         m_AEMD.autotype    != m_AEMD.pci->GetAutoType()   ||
                         m_AEMD.runcommand  != m_AEMD.pci->GetRunCommand() ||
                         m_AEMD.DCA         != iDCA                        ||
                         m_AEMD.ShiftDCA    != iShiftDCA                   ||
                         m_AEMD.email       != m_AEMD.pci->GetEmail()      ||
                         m_AEMD.symbols     != m_AEMD.oldsymbols           ||
                         m_AEMD.PWHistory   != m_AEMD.pci->GetPWHistory()  ||
                         m_AEMD.locXTime    != m_AEMD.oldlocXTime          ||
                         m_AEMD.XTimeInt    != m_AEMD.oldXTimeInt          ||
                         m_AEMD.ipolicy     != m_AEMD.oldipolicy           ||
                        (m_AEMD.ipolicy     == SPECIFIC_POLICY &&
                         m_AEMD.pwp         != m_AEMD.oldpwp)              ||
                        (m_AEMD.ipolicy     == NAMED_POLICY &&
                         m_AEMD.policyname  != m_AEMD.oldpolicyname)       ||
                         m_AEMD.KBShortcut  != m_AEMD.oldKBShortcut);

        bIsPSWDModified = (m_AEMD.realpassword != m_AEMD.oldRealPassword);

        if (m_bIsModified) {
          // Just modify all - even though only 1 may have actually been modified
          m_AEMD.pci->SetGroup(m_AEMD.group);
          m_AEMD.pci->SetTitle(m_AEMD.title);
          m_AEMD.pci->SetUser(m_AEMD.username.IsEmpty() ?
                                   m_AEMD.defusername : m_AEMD.username);
          if (m_bNotesChanged)
            m_AEMD.pci->SetNotes(m_AEMD.realnotes);

          m_AEMD.pci->SetURL(m_AEMD.URL);
          m_AEMD.pci->SetAutoType(m_AEMD.autotype);
          m_AEMD.pci->SetPWHistory(m_AEMD.PWHistory);
          m_AEMD.PWHistory = m_AEMD.PWHistory;
          m_AEMD.oldNumPWHistory = m_AEMD.NumPWHistory;
          m_AEMD.oldMaxPWHistory = m_AEMD.MaxPWHistory;
          m_AEMD.oldSavePWHistory = m_AEMD.SavePWHistory;		 
          switch (m_AEMD.ipolicy) {
            case DEFAULT_POLICY:
              m_AEMD.pci->SetPWPolicy(L"");
              m_AEMD.policyname = L"";
              m_AEMD.pci->SetPolicyName(L"");
              break;
            case NAMED_POLICY:
              m_AEMD.pci->SetPWPolicy(L"");
              m_AEMD.pci->SetPolicyName(m_AEMD.policyname);
              break;
            case SPECIFIC_POLICY:
              m_AEMD.pci->SetPWPolicy(m_AEMD.pwp);
              m_AEMD.policyname = L"";
              m_AEMD.pci->SetPolicyName(L"");
              break;
           }

          m_AEMD.oldipolicy = m_AEMD.ipolicy;
          m_AEMD.oldpwp = m_AEMD.pwp;
          m_AEMD.oldsymbols = m_AEMD.symbols;
          m_AEMD.oldpolicyname = m_AEMD.policyname;

          m_AEMD.pci->SetRunCommand(m_AEMD.runcommand);
          m_AEMD.pci->SetDCA(m_AEMD.DCA);
          m_AEMD.pci->SetShiftDCA(m_AEMD.ShiftDCA);
          m_AEMD.pci->SetEmail(m_AEMD.email);
          m_AEMD.pci->SetSymbols(m_AEMD.symbols);
          m_AEMD.pci->SetProtected(m_AEMD.ucprotected != 0);

          m_AEMD.oldKBShortcut = m_AEMD.KBShortcut;
          m_AEMD.pci->SetKBShortcut(m_AEMD.KBShortcut);
        }

        m_AEMD.pci->SetXTimeInt(m_AEMD.XTimeInt);

        if (bIsPSWDModified || m_AEMD.locXTime != m_AEMD.oldlocXTime) {
          CItemData *pciA(m_AEMD.pci);
          if (m_AEMD.pci->IsAlias()) {
            pciA = m_AEMD.pcore->GetBaseEntry(m_AEMD.pci);
          }

          if (bIsPSWDModified) {
            m_AEMD.pci->UpdatePassword(m_AEMD.realpassword);
            m_AEMD.locPMTime = pciA->GetPMTimeL();
          }

          if (m_AEMD.locXTime != m_AEMD.oldlocXTime) {
            pciA->SetXTime(m_AEMD.tttXTime);
            m_AEMD.locXTime = pciA->GetXTimeL();
            m_AEMD.oldlocXTime = m_AEMD.locXTime;
          }
        }

        if (m_bIsModified && !bIsPSWDModified) {
          time(&t);
          m_AEMD.pci->SetRMTime(t);
        }

        if (m_bIsModified)
          SendMessage(PSM_QUERYSIBLINGS,
                (WPARAM)CPWPropertyPage::PP_UPDATE_TIMES, 0L);

        m_bIsModified = m_bIsModified || bIsPSWDModified;
        break;

      case IDS_ADDENTRY:
        m_bIsModified = true;
        m_AEMD.pci->SetGroup(m_AEMD.group);
        m_AEMD.pci->SetTitle(m_AEMD.title);
        m_AEMD.pci->SetUser(m_AEMD.username.IsEmpty() ?
                                 m_AEMD.defusername : m_AEMD.username);
        m_AEMD.pci->SetPassword(m_AEMD.realpassword);
        m_AEMD.pci->SetNotes(m_AEMD.realnotes);
        m_AEMD.pci->SetURL(m_AEMD.URL);
        m_AEMD.pci->SetAutoType(m_AEMD.autotype);
        m_AEMD.pci->SetRunCommand(m_AEMD.runcommand);
        m_AEMD.pci->SetDCA(m_AEMD.DCA);
        m_AEMD.pci->SetShiftDCA(m_AEMD.ShiftDCA);
        m_AEMD.pci->SetEmail(m_AEMD.email);
        m_AEMD.pci->SetSymbols(m_AEMD.symbols);
        m_AEMD.pci->SetProtected(m_AEMD.ucprotected != 0);
        m_AEMD.pci->SetKBShortcut(m_AEMD.KBShortcut);

        time(&t);
        m_AEMD.pci->SetCTime(t);

        if (m_AEMD.XTimeInt > 0 && m_AEMD.XTimeInt <= 3650)
          m_AEMD.pci->SetXTimeInt(m_AEMD.XTimeInt);

        if (m_AEMD.SavePWHistory == TRUE)
          m_AEMD.pci->SetPWHistory(MakePWHistoryHeader(TRUE, m_AEMD.MaxPWHistory, 0));

        if (m_AEMD.ibasedata > 0) {
          // Password in alias format AND base entry exists
          // No need to check if base is an alias as already done in
          // call to PWScore::ParseBaseEntryPWD
          m_AEMD.pci->SetPassword(L"[Alias]");
          m_AEMD.pci->SetAlias();
          ItemListIter iter = m_AEMD.pcore->Find(m_AEMD.base_uuid);
          if (iter != GetMainDlg()->End())
            GetMainDlg()->UpdateEntryImages(iter->second);
        } else {
          m_AEMD.pci->SetPassword(m_AEMD.realpassword);
          m_AEMD.pci->SetNormal();
        }

        if (m_AEMD.pci->IsAlias()) {
          m_AEMD.pci->SetXTime((time_t)0);
          m_AEMD.pci->SetPWPolicy(L"");
        } else {
          m_AEMD.pci->SetXTime(m_AEMD.tttXTime);

          switch (m_AEMD.ipolicy) {
            case DEFAULT_POLICY:
              m_AEMD.pci->SetPWPolicy(L"");
              m_AEMD.policyname = L"";
              m_AEMD.pci->SetPolicyName(L"");
              break;
            case NAMED_POLICY:
              m_AEMD.pci->SetPWPolicy(L"");
              m_AEMD.pci->SetPolicyName(m_AEMD.policyname);
              break;
            case SPECIFIC_POLICY:
              m_AEMD.pci->SetPWPolicy(m_AEMD.pwp);
              m_AEMD.policyname = L"";
              m_AEMD.pci->SetPolicyName(L"");
              break;
          }
        }

        if (m_bIsModified)
          SendMessage(PSM_QUERYSIBLINGS,
                (WPARAM)CPWPropertyPage::PP_UPDATE_TIMES, 0L);
        break;
      case IDS_VIEWENTRY:
        // No Update
        break;
      default:
        ASSERT(0);
        break;
    }

    // Now end it all so that OnApply isn't called again
    if (iCID == IDOK) {
      // Just end it
      CPWPropertySheet::EndDialog(IDOK);
    } else {
      // Send message to DboxMain to update entry
      GetMainDlg()->SendMessage(PWS_MSG_EDIT_APPLY, (WPARAM)this, NULL);

      // Now make the original equal to new intermediate state
      *(m_AEMD.pci_original) = *(m_AEMD.pci);

      // Now Reset starting values
      SetupInitialValues();
      SetChanged(false);
    }
    m_AEMD.entrysize = m_AEMD.pci->GetSize();
    m_pp_datetimes->UpdateStats();
    return TRUE;
  }

  return CPWPropertySheet::OnCommand(wParam, lParam);
}

BOOL CAddEdit_PropertySheet::PreTranslateMessage(MSG* pMsg)
{
  // In View mode, there is no 'Cancel' button and 'OK' is renamed 'Close'
  // Make Escape key still work as designed
  if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) {
    if (m_AEMD.uicaller == IDS_VIEWENTRY || m_AEMD.ucprotected != 0) {
      CPWPropertySheet::EndDialog(IDCANCEL);
      return TRUE;
    } else {
      // Ask user whether to allow Escape to cancel
      CPWPropertyPage *pp = (CPWPropertyPage *)GetActivePage();
      BOOL brc = pp->OnQueryCancel();
      if (brc == TRUE)
        CPWPropertySheet::EndDialog(IDCANCEL);
     
      return TRUE;
    }
  }

  if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_F1) {
    CAddEdit_PropertyPage *pp = (CAddEdit_PropertyPage *)GetActivePage();
    pp->PostMessage(WM_COMMAND, MAKELONG(ID_HELP, BN_CLICKED), NULL);
    return TRUE;
  }

  return CPWPropertySheet::PreTranslateMessage(pMsg);
}

void CAddEdit_PropertySheet::SetupInitialValues()
{
  // Basic Data
  m_AEMD.entrysize = m_AEMD.pci->GetSize();
  m_AEMD.entry_uuid = m_AEMD.pci->GetUUID();
  m_AEMD.group = m_AEMD.pci->GetGroup();
  m_AEMD.title = m_AEMD.pci->GetTitle();
  m_AEMD.username = m_AEMD.pci->GetUser();
  m_AEMD.realpassword = m_AEMD.oldRealPassword = m_AEMD.pci->GetPassword();
  m_AEMD.realnotes = m_AEMD.originalrealnotesTRC = m_AEMD.pci->GetNotes();
  m_AEMD.URL = m_AEMD.pci->GetURL();
  m_AEMD.email = m_AEMD.pci->GetEmail();
  m_AEMD.symbols = m_AEMD.oldsymbols = m_AEMD.pci->GetSymbols();
  m_AEMD.ioldownsymbols = m_AEMD.symbols.IsEmpty() == TRUE ?
                            DEFAULT_SYMBOLS : OWN_SYMBOLS;
  m_AEMD.iownsymbols = m_AEMD.ioldownsymbols;
  m_AEMD.pci->GetProtected(m_AEMD.ucprotected);

  if (m_AEMD.realnotes.GetLength() > MAXTEXTCHARS) {
    // Limit the Notes field to what can be displayed
    m_AEMD.realnotes =  m_AEMD.realnotes.Left(MAXTEXTCHARS);
    m_AEMD.originalrealnotesTRC = m_AEMD.realnotes;
    CGeneralMsgBox gmb;
    CString cs_text, cs_title(MAKEINTRESOURCE(IDS_WARNINGTEXTLENGTH));
    cs_text.Format(IDS_TRUNCATETEXT, MAXTEXTCHARS);
    gmb.MessageBox(cs_text, cs_title, MB_OK | MB_ICONEXCLAMATION);
  }

  // Entry type initialisation
  m_AEMD.original_entrytype = m_AEMD.pci->GetEntryType();

  const CItemData *pciA(m_AEMD.pci);
  if (m_AEMD.pci->IsAlias()) {
    pciA = m_AEMD.pcore->GetBaseEntry(m_AEMD.pci);
    if (pciA == NULL) {
      CString err(MAKEINTRESOURCE(IDS_ABASE_MISSING));
      throw err;
    }
  }

  // Additional data
  m_AEMD.autotype = m_AEMD.pci->GetAutoType();
  m_AEMD.runcommand = m_AEMD.pci->GetRunCommand();
  m_AEMD.pci->GetDCA(m_AEMD.DCA);
  m_AEMD.oldDCA = m_AEMD.DCA;
  m_AEMD.pci->GetShiftDCA(m_AEMD.ShiftDCA);
  m_AEMD.oldShiftDCA = m_AEMD.ShiftDCA;
  
  m_AEMD.pci->GetKBShortcut(m_AEMD.KBShortcut);
  m_AEMD.oldKBShortcut = m_AEMD.KBShortcut;

  // Date Time fields
  m_AEMD.locCTime = m_AEMD.pci->GetCTimeL();
  if (m_AEMD.locCTime.IsEmpty())
    m_AEMD.locCTime.LoadString(IDS_NA);

  m_AEMD.locATime = m_AEMD.pci->GetATimeL();
  if (m_AEMD.locATime.IsEmpty())
    m_AEMD.locATime.LoadString(IDS_NA);

  m_AEMD.locRMTime = m_AEMD.pci->GetRMTimeL();
  if (m_AEMD.locRMTime.IsEmpty())
    m_AEMD.locRMTime.LoadString(IDS_NA);

  m_AEMD.locPMTime = m_AEMD.pci->GetPMTimeL();
  if (m_AEMD.locPMTime.IsEmpty())
    m_AEMD.locPMTime.LoadString(IDS_NA);

  if (!m_AEMD.locPMTime.IsEmpty())
    m_AEMD.pci->GetPMTime(m_AEMD.tttCPMTime);

  if ((long)m_AEMD.tttCPMTime == 0L) // if never changed - try creation date
    m_AEMD.pci->GetCTime(m_AEMD.tttCPMTime);

  // Note different pci depending on if Alias
  m_AEMD.locXTime = pciA->GetXTimeL();
  if (m_AEMD.locXTime.IsEmpty()) {
    m_AEMD.locXTime.LoadString(IDS_NEVER);
    m_AEMD.tttXTime = 0;
  } else {
    pciA->GetXTime(m_AEMD.tttXTime);
  }
  m_AEMD.oldlocXTime = m_AEMD.locXTime;

  // Note different pci depending on if Alias
  pciA->GetXTimeInt(m_AEMD.XTimeInt);
  m_AEMD.oldXTimeInt = m_AEMD.XTimeInt;

  // PWHistory fields
  // Note different pci depending on if Alias
  size_t num_err;
  m_AEMD.PWHistory = pciA->GetPWHistory();
  BOOL HasHistory = CreatePWHistoryList(m_AEMD.PWHistory,
                                        m_AEMD.MaxPWHistory,
                                        num_err,
                                        m_AEMD.pwhistlist,
                                        PWSUtil::TMC_EXPORT_IMPORT) ? TRUE : FALSE;
  m_AEMD.oldNumPWHistory = m_AEMD.NumPWHistory = m_AEMD.pwhistlist.size();
  m_AEMD.oldSavePWHistory = m_AEMD.SavePWHistory = HasHistory;
  if (m_AEMD.MaxPWHistory == 0)
    m_AEMD.MaxPWHistory = PWSprefs::GetInstance()->
                           GetPref(PWSprefs::NumPWHistoryDefault);
  // PWPolicy fields
  // Note different pci depending on if Alias
  pciA->GetPWPolicy(m_AEMD.pwp);
  m_AEMD.policyname = m_AEMD.oldpolicyname = pciA->GetPolicyName();

  if (!m_AEMD.policyname.IsEmpty())
    m_AEMD.ipolicy = NAMED_POLICY;
  else
  if (pciA->GetPWPolicy().empty())
    m_AEMD.ipolicy = DEFAULT_POLICY;
  else
    m_AEMD.ipolicy = SPECIFIC_POLICY;

  m_AEMD.oldipolicy = m_AEMD.ipolicy;

  if (m_AEMD.ipolicy == DEFAULT_POLICY) {
    m_AEMD.pwp = m_AEMD.default_pwp;
  }

  m_AEMD.oldpwp = m_AEMD.pwp;

  // Set up dependents
  pws_os::CUUID original_base_uuid(pws_os::CUUID::NullUUID());
  CItemData::EntryType entrytype = m_AEMD.pci_original->GetEntryType();

  pws_os::CUUID original_uuid = m_AEMD.pci_original->GetUUID();  // Edit doesn't change this!
  if (m_AEMD.pci_original->IsBase()) {
    UUIDVector dependentslist;
    StringX csDependents(L"");

    m_AEMD.pcore->GetAllDependentEntries(original_uuid, dependentslist,
                                  m_AEMD.pci_original->IsAliasBase() ?
                                  CItemData::ET_ALIAS : CItemData::ET_SHORTCUT);
    size_t num_dependents = dependentslist.size();
    if (num_dependents > 0) {
      m_AEMD.pcore->SortDependents(dependentslist, csDependents);
    }

    m_AEMD.num_dependents = (int)num_dependents;
    m_AEMD.original_entrytype = entrytype;
    m_AEMD.dependents = CSecString(csDependents);
    dependentslist.clear();
  } else
  if (m_AEMD.pci_original->IsAlias()) {
    // Get corresponding base entry
    const CItemData *pbci = m_AEMD.pcore->GetBaseEntry(m_AEMD.pci_original);
    ASSERT(pbci != NULL);
    if (pbci != NULL) {
      original_base_uuid = pbci->GetUUID();
      m_AEMD.base_uuid = original_base_uuid;
      CSecString cs_base = L"[" +
                           pbci->GetGroup() + L":" +
                           pbci->GetTitle() + L":" +
                           pbci->GetUser()  + L"]";
      m_AEMD.base = cs_base;
      m_AEMD.original_entrytype = CItemData::ET_ALIAS;
    }
  } // IsAlias
}
