void PHPCodeCompletion::DoShowCompletionBox(const PHPEntityBase::List_t& entries, PHPExpression::Ptr_t expr)
{
    wxCodeCompletionBoxEntry::Vec_t ccEntries;
    TagEntryPtrVector_t tags;
    wxStringSet_t uniqueEntries;

    // search for the old item
    PHPEntityBase::List_t::const_iterator iter = entries.begin();
    for(; iter != entries.end(); ++iter) {
        PHPEntityBase::Ptr_t entry = *iter;
        if(uniqueEntries.count(entry->GetFullName()) == 0) {
            uniqueEntries.insert(entry->GetFullName());
        } else {
            // don't add duplicate entries
            continue;
        }

        PHPEntityBase::Ptr_t ns = expr->GetSourceFile()->Namespace(); // the namespace at the source file
        TagEntryPtr t = DoPHPEntityToTagEntry(entry);

        tags.push_back(t);
    }

    std::sort(tags.begin(), tags.end(), _SAscendingSort());
    for(size_t i = 0; i < tags.size(); ++i) {
        wxCodeCompletionBoxEntry::Ptr_t ccEntry = wxCodeCompletionBox::TagToEntry(tags.at(i));
        ccEntry->SetComment(tags.at(i)->GetComment());
        ccEntries.push_back(ccEntry);
    }
    wxCodeCompletionBoxManager::Get().ShowCompletionBox(
        m_manager->GetActiveEditor()->GetCtrl(), ccEntries, wxCodeCompletionBox::kRefreshOnKeyType, wxNOT_FOUND);
}
void PHPCodeCompletion::OnFunctionCallTip(clCodeCompletionEvent& e)
{
    e.Skip();
    if(PHPWorkspace::Get()->IsOpen()) {
        if(!CanCodeComplete(e)) return;

        IEditor* editor = dynamic_cast<IEditor*>(e.GetEditor());
        if(editor) {
            // we handle only .php files
            if(IsPHPFile(editor)) {

                // this is our to complete
                e.Skip(false);

                // get the position
                PHPEntityBase::Ptr_t resolved = DoGetPHPEntryUnderTheAtPos(editor, editor->GetCurrentPosition(), true);
                if(resolved) {
                    // In PHP there is no overloading, so there can be only one signature for a function
                    // so we simply place our match into TagEntryPtrVector_t structure and pass it to the editor
                    TagEntryPtrVector_t tags;
                    tags.push_back(DoPHPEntityToTagEntry(resolved));
                    clCallTipPtr callTip(new clCallTip(tags));
                    editor->ShowCalltip(callTip);
                }
            }
        }
    }
}
void PHPCodeCompletion::DoShowCompletionBox(const PHPEntityBase::List_t& entries, PHPExpression::Ptr_t expr)
{
    std::vector<TagEntryPtr> tags;
    wxStringSet_t uniqueEntries;

    // search for the old item
    PHPEntityBase::List_t::const_iterator iter = entries.begin();
    for(; iter != entries.end(); ++iter) {
        PHPEntityBase::Ptr_t entry = *iter;
        if(uniqueEntries.count(entry->GetFullName()) == 0) {
            uniqueEntries.insert(entry->GetFullName());
        } else {
            // don't add duplicate entries
            continue;
        }

        PHPEntityBase::Ptr_t ns = expr->GetSourceFile()->Namespace(); // the namespace at the source file
        TagEntryPtr t = DoPHPEntityToTagEntry(entry);
        t->SetUserData(new PHPCCUserData(entry));
        tags.push_back(t);
    }

    if(tags.empty()) return;

    std::sort(tags.begin(), tags.end(), _SAscendingSort());
    m_manager->GetActiveEditor()->ShowCompletionBox(tags, expr->GetFilter(), false, this);
}
void PHPCodeCompletion::OnFindSymbol(clCodeCompletionEvent& e)
{
    e.Skip();
    if(PHPWorkspace::Get()->IsOpen()) {
        if(!CanCodeComplete(e)) return;
        e.Skip(false);
        IEditor* editor = dynamic_cast<IEditor*>(e.GetEditor());
        if(editor) {
            wxString word = editor->GetWordAtCaret();
            if(word.IsEmpty()) return;
            PHPEntityBase::List_t symbols = m_lookupTable.FindSymbol(word);
            if(symbols.size() == 1) {
                PHPEntityBase::Ptr_t match = *symbols.begin();
                DoOpenEditorForEntry(match);

            } else {

                // Convert the matches to clSelectSymbolDialogEntry::List_t
                clSelectSymbolDialogEntry::List_t entries;
                std::for_each(symbols.begin(), symbols.end(), [&](PHPEntityBase::Ptr_t entry) {
                    TagEntryPtr tag = DoPHPEntityToTagEntry(entry);
                    wxBitmap bmp = wxCodeCompletionBox::GetBitmap(tag);

                    clSelectSymbolDialogEntry m;
                    m.bmp = bmp;
                    m.name = entry->GetFullName();
                    m.clientData = new PHPFindSymbol_ClientData(entry);
                    m.help = tag->GetKind();
                    entries.push_back(m);
                });

                // Show selection dialog
                clSelectSymbolDialog dlg(EventNotifier::Get()->TopFrame(), entries);
                if(dlg.ShowModal() != wxID_OK) return;
                PHPFindSymbol_ClientData* cd = dynamic_cast<PHPFindSymbol_ClientData*>(dlg.GetSelection());
                if(cd) {
                    DoOpenEditorForEntry(cd->m_ptr);
                }
            }
        }
    }
}