//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// copyright            : (C) 2008 by Eran Ifrah
// file name            : newkeyshortcutdlg.cpp
//
// -------------------------------------------------------------------------
// A
//              _____           _      _     _ _
//             /  __ \         | |    | |   (_) |
//             | /  \/ ___   __| | ___| |    _| |_ ___
//             | |    / _ \ / _  |/ _ \ |   | | __/ _ )
//             | \__/\ (_) | (_| |  __/ |___| | ||  __/
//              \____/\___/ \__,_|\___\_____/_|\__\___|
//
//                                                  F i l e
//
//    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 "newkeyshortcutdlg.h"
#include <wx/tokenzr.h>
#include "windowattrmanager.h"
#include "clSingleChoiceDialog.h"

static const struct wxKeyName {
    wxKeyCode code;
    const char* name;
} wxKeyNames[] = {
    { WXK_DELETE, wxTRANSLATE("DEL") }, { WXK_DELETE, wxTRANSLATE("DELETE") }, { WXK_BACK, wxTRANSLATE("BACK") },
    { WXK_INSERT, wxTRANSLATE("INS") }, { WXK_RETURN, wxTRANSLATE("ENTER") }, { WXK_RETURN, wxTRANSLATE("RETURN") },
    { WXK_PAGEUP, wxTRANSLATE("PGUP") }, { WXK_PAGEDOWN, wxTRANSLATE("PGDN") }, { WXK_LEFT, wxTRANSLATE("LEFT") },
    { WXK_RIGHT, wxTRANSLATE("RIGHT") }, { WXK_UP, wxTRANSLATE("UP") }, { WXK_DOWN, wxTRANSLATE("DOWN") },
    { WXK_HOME, wxTRANSLATE("HOME") }, { WXK_END, wxTRANSLATE("END") }, { WXK_SPACE, wxTRANSLATE("SPACE") },
    { WXK_TAB, wxTRANSLATE("TAB") }, { WXK_ESCAPE, wxTRANSLATE("ESC") }, { WXK_ESCAPE, wxTRANSLATE("ESCAPE") },
    { WXK_CANCEL, wxTRANSLATE("CANCEL") }, { WXK_CLEAR, wxTRANSLATE("CLEAR") }, { WXK_MENU, wxTRANSLATE("MENU") },
    { WXK_PAUSE, wxTRANSLATE("PAUSE") }, { WXK_CAPITAL, wxTRANSLATE("CAPITAL") }, { WXK_SELECT, wxTRANSLATE("SELECT") },
    { WXK_PRINT, wxTRANSLATE("PRINT") }, { WXK_EXECUTE, wxTRANSLATE("EXECUTE") },
    { WXK_SNAPSHOT, wxTRANSLATE("SNAPSHOT") }, { WXK_HELP, wxTRANSLATE("HELP") }, { WXK_ADD, wxTRANSLATE("ADD") },
    { WXK_SEPARATOR, wxTRANSLATE("SEPARATOR") }, { WXK_SUBTRACT, wxTRANSLATE("SUBTRACT") },
    { WXK_DECIMAL, wxTRANSLATE("DECIMAL") }, { WXK_DIVIDE, wxTRANSLATE("DIVIDE") },
    { WXK_NUMLOCK, wxTRANSLATE("NUM_LOCK") }, { WXK_SCROLL, wxTRANSLATE("SCROLL_LOCK") },
    { WXK_PAGEUP, wxTRANSLATE("PAGEUP") }, { WXK_PAGEDOWN, wxTRANSLATE("PAGEDOWN") },
    { WXK_NUMPAD_SPACE, wxTRANSLATE("SPACE") }, { WXK_NUMPAD_TAB, wxTRANSLATE("TAB") },
    { WXK_NUMPAD_ENTER, wxTRANSLATE("ENTER") }, { WXK_NUMPAD_HOME, wxTRANSLATE("HOME") },
    { WXK_NUMPAD_LEFT, wxTRANSLATE("LEFT") }, { WXK_NUMPAD_UP, wxTRANSLATE("UP") },
    { WXK_NUMPAD_RIGHT, wxTRANSLATE("RIGHT") }, { WXK_NUMPAD_DOWN, wxTRANSLATE("DOWN") },
    { WXK_NUMPAD_PAGEUP, wxTRANSLATE("PRIOR") }, { WXK_NUMPAD_PAGEUP, wxTRANSLATE("PGUP") },
    { WXK_NUMPAD_PAGEDOWN, wxTRANSLATE("NEXT") }, { WXK_NUMPAD_PAGEDOWN, wxTRANSLATE("PGDN") },
    { WXK_NUMPAD_END, wxTRANSLATE("END") }, { WXK_NUMPAD_BEGIN, wxTRANSLATE("BEGIN") },
    { WXK_NUMPAD_INSERT, wxTRANSLATE("INS") }, { WXK_NUMPAD_DELETE, wxTRANSLATE("DEL") },
    { WXK_NUMPAD_EQUAL, wxTRANSLATE("=") }, { WXK_NUMPAD_MULTIPLY, wxTRANSLATE("*") },
    { WXK_NUMPAD_ADD, wxTRANSLATE("+") }, { WXK_NUMPAD_SEPARATOR, wxTRANSLATE("KP_SEPARATOR") },
    { WXK_NUMPAD_SUBTRACT, wxTRANSLATE("-") }, { WXK_NUMPAD_DECIMAL, wxTRANSLATE(".") },
    { WXK_NUMPAD_DIVIDE, wxTRANSLATE("/") }, { WXK_WINDOWS_LEFT, wxTRANSLATE("WINDOWS_LEFT") },
    { WXK_WINDOWS_RIGHT, wxTRANSLATE("WINDOWS_RIGHT") }, { WXK_WINDOWS_MENU, wxTRANSLATE("WINDOWS_MENU") },
    { WXK_COMMAND, wxTRANSLATE("COMMAND") },
};

NewKeyShortcutDlg::NewKeyShortcutDlg(wxWindow* parent, const MenuItemData& mid)
    : NewKeyShortcutBaseDlg(parent)
    , m_mid(mid)
{
#ifdef __WXOSX__
    m_checkBoxCtrl->SetLabel("Cmd");
#else
    m_checkBoxCtrl->SetLabel("Ctrl");
#endif
    CentreOnParent();
    GetSizer()->Fit(this);
    Initialise(mid.accel);
}


void NewKeyShortcutDlg::Initialise(const wxString& accel)
{
    NewKeyShortcutDlg::KeyboardShortcut ks = FromString(accel);
    m_staticTextAction->SetLabel(m_mid.action);
    m_textCtrl1->ChangeValue(ks.key);

    m_checkBoxAlt->SetValue(ks.modifiers & kAlt);
    m_checkBoxCtrl->SetValue(ks.modifiers & kCtrl);
    m_checkBoxShift->SetValue(ks.modifiers & kShift);
}

void NewKeyShortcutDlg::OnKeyDown(wxKeyEvent& event)
{
    wxString text = ToString(event);
    if(text.IsEmpty()) {
        return;
    }
    m_textCtrl1->ChangeValue(text);
}

wxString NewKeyShortcutDlg::ToString(wxKeyEvent& e)
{
    wxString text;

    // int flags = e.GetModifiers();
    // if ( flags & wxMOD_ALT )
    //     text += wxT("Alt-");
    // if ( flags & wxMOD_CONTROL )
    //     text += wxT("Ctrl-");
    // if ( flags & wxMOD_SHIFT )
    //     text += wxT("Shift-");

    const int code = e.GetKeyCode();

    if(code >= WXK_F1 && code <= WXK_F12)
        text << _("F") << code - WXK_F1 + 1;
    else if(code >= WXK_NUMPAD0 && code <= WXK_NUMPAD9)
        text << code - WXK_NUMPAD0;
    else if(code >= WXK_SPECIAL1 && code <= WXK_SPECIAL20)
        text << _("SPECIAL") << code - WXK_SPECIAL1 + 1;
    else { // check the named keys
        size_t n;
        for(n = 0; n < WXSIZEOF(wxKeyNames); n++) {
            const wxKeyName& kn = wxKeyNames[n];
            if(code == kn.code && kn.code != WXK_COMMAND) {
                text << wxGetTranslation(kn.name);
                break;
            }
        }

        if(n == WXSIZEOF(wxKeyNames)) {
            // must be a simple key
            if(isascii(code)) {
                text << (wxChar)code;
            } else {
                return wxEmptyString;
            }
        }
    }

    return text;
}

NewKeyShortcutDlg::KeyboardShortcut NewKeyShortcutDlg::FromString(const wxString& accelString)
{
    wxString tmp_accel = accelString;
    tmp_accel.MakeLower();

    NewKeyShortcutDlg::KeyboardShortcut ks;
    wxArrayString tokens = ::wxStringTokenize(accelString, "-+", wxTOKEN_STRTOK);

    for(size_t i = 0; i < tokens.GetCount(); ++i) {
        wxString token = tokens.Item(i);
        token.MakeLower();
        if(token == "shift") {
            ks.modifiers |= kShift;
        } else if(token == "alt") {
            ks.modifiers |= kAlt;
        } else if(token == "ctrl") {
            ks.modifiers |= kCtrl;
        } else {
            ks.key = tokens.Item(i);
        }
    }
    return ks;
}

wxString NewKeyShortcutDlg::GetAccel() const
{
    wxString accel;
    if(m_checkBoxCtrl->IsChecked()) accel << "Ctrl-";
    if(m_checkBoxAlt->IsChecked()) accel << "Alt-";
    if(m_checkBoxShift->IsChecked()) accel << "Shift-";
    accel << m_textCtrl1->GetValue();
    if(accel.EndsWith("-")) {
        accel.RemoveLast();
    }
    return accel;
}

void NewKeyShortcutDlg::OnClear(wxCommandEvent& event)
{
    // Clear the modifiers checkboxs
    m_checkBoxAlt->SetValue(false);
    m_checkBoxCtrl->SetValue(false);
    m_checkBoxShift->SetValue(false);

    m_textCtrl1->ChangeValue("");
}

void NewKeyShortcutDlg::OnClearUI(wxUpdateUIEvent& event)
{
    event.Enable(m_checkBoxAlt->IsChecked() || m_checkBoxCtrl->IsChecked() || m_checkBoxShift->IsChecked() ||
        !m_textCtrl1->IsEmpty());
}

NewKeyShortcutDlg::~NewKeyShortcutDlg() {}

void NewKeyShortcutDlg::OnSuggest(wxCommandEvent& event)
{
    clSingleChoiceDialog dlg(this, clKeyboardManager::Get()->GetAllUnasignedKeyboardShortcuts(), 0);
    dlg.SetLabel(_("Select a Keyboard Shortcut"));
    if(dlg.ShowModal() == wxID_OK) {
        Initialise(dlg.GetSelection());
    }
}
