/*

MAgen.dll: Miranda plugin for mail.ru message exchange.

Copyright 2005-2010 Lenik.
Project home at http://www.lenik.ru/win32/magent
Author contact: lenik@lenik.ru

This program is free software.

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.

*/

#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <time.h>
#include <stddef.h>
#include <process.h>
#include <string.h>
#include <winsock.h>
#include <process.h>
#include <winbase.h>

#include "resource.h"
#include "magent.h"
#include "Include/newpluginapi.h"
#include "Include/m_clist.h"
#include "Include/m_clui.h"
#include "Include/m_skin.h"
#include "Include/m_langpack.h"
#include "Include/m_protomod.h"
#include "Include/m_database.h"
#include "Include/m_system.h"
#include "Include/m_protocols.h"
#include "Include/m_userinfo.h"
#include "Include/m_options.h"
#include "Include/m_protosvc.h"
#include "Include/m_utils.h"
#include "Include/m_ignore.h"
#include "Include/m_clc.h"
#include "Include/m_contacts.h"
#include "Include/m_netlib.h"

#pragma pack(1)

#include "../../copyright.c"

#include "resource.h"

unsigned char ProtoName[100] = "";
#include "magent-services.c"

unsigned long Sequence = 0x0;
unsigned long GetSequenceNext(void){Sequence++;return(Sequence);}

unsigned long MRIM_Flag_ContactListReceiving = 0;
HANDLE hContactDeletedHook = NULL;
HANDLE hContactModifyHook = NULL;
HANDLE hHookOptInit = NULL;
HANDLE hHookUserInfoInit = NULL;
HANDLE hServerNetlibUser = 0;
HANDLE MRIM_hServerConn = 0;
HANDLE MRIM_hServerPacketRecver = 0;
HANDLE MRIM_t_hServerConn = 0;
HANDLE MRIM_t_hServerPacketRecver = 0;
unsigned long MRIM_Status = ID_STATUS_OFFLINE;
unsigned long MRIM_NewMessagesCount = 0;
unsigned long MRIM_LoginInProgressFlag = 0;
static HANDLE hUserMenu = NULL;
HINSTANCE HInstance;
PLUGINLINK *pluginLink;

#include "!magent-plugininfo.c"
#ifdef MRIM_DEBUG
    #include "debug.c"
#endif
#include "proto.h"
#include "mrim_options.h"

unsigned char ModuleName_Text[] = "Miranda Plugin for Mail.Ru Agent Protocol. (C) 2005-2010 Lenik";
#define CODEBLOCK
unsigned long   MRIM_WatchDogInterval = 30;

#include "mrim_core.c"

time_t gettimestamp(void)
{
SYSTEMTIME st;
FILETIME ft;
__int64 tmpqw;

GetSystemTime(&st);
SystemTimeToFileTime(&st,&ft);

tmpqw = *((__int64*)(&ft));
tmpqw /= (__int64)10000000;
tmpqw -= (__int64)11644473600;
return((time_t)tmpqw);
}

HANDLE HContactFromEMail(unsigned char *email,int allowAdd,unsigned long inlistflag)
{
HANDLE hContact;
char* szProto;
DBVARIANT dbv;

hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
while(hContact != NULL)
    {
    szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);

    if((szProto != NULL)&&(!strcmp(szProto,ProtoName)))
        {
        DBGetContactSetting(hContact,ProtoName,DB_SETTING_EMAIL, &dbv);
        if(strcmp(dbv.pszVal,email) == 0)
            return(hContact);
        }
    hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
    }
//not present: add
if(allowAdd)
    {
    hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0);
    CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)ProtoName);

    DBWriteContactSettingString(hContact,ProtoName,DB_SETTING_EMAIL,email);
    DBWriteContactSettingByte(hContact,DB_SETTING_CLIST, "NotOnList",inlistflag==1?0:1);
    DBWriteContactSettingString(hContact,DB_SETTING_CLIST,DB_SETTING_CLIST_MYHANDLE,email);
    DBWriteContactSettingByte(hContact,DB_SETTING_CLIST, "Hidden", 0);

    return(hContact);
    }
return(INVALID_HANDLE_VALUE);
}

unsigned long ConvertMirandaStatusToMRIM(unsigned long status)
{
switch(status)
    {
    case ID_STATUS_ONLINE:
        status = STATUS_ONLINE;
        break;
    case ID_STATUS_INVISIBLE:
        status = STATUS_ONLINE|STATUS_FLAG_INVISIBLE;
        break;
    case ID_STATUS_AWAY:
        status = STATUS_AWAY;
        break;
    default:
        status = STATUS_OFFLINE;
    }
return(status);
}

unsigned long ConvertMRIMStatusToMiranda(unsigned long status)
{
switch(status)
    {
    case STATUS_ONLINE:
    case STATUS_FLAG_INVISIBLE:
        status = ID_STATUS_ONLINE;
        break;
    case STATUS_ONLINE|STATUS_FLAG_INVISIBLE:
        status = ID_STATUS_INVISIBLE;
        break;
    case STATUS_AWAY:
        status = ID_STATUS_AWAY;
        break;
    default:
        status = ID_STATUS_OFFLINE;
    }
return(status);
}

HANDLE MRIM_SetMirandaStatus(unsigned char *fromaddr,unsigned long status)
{
HANDLE hContact;

status = ConvertMRIMStatusToMiranda(status);
if((hContact=HContactFromEMail(fromaddr,0,0)) != NULL)
    {
    DBWriteContactSettingWord(hContact,ProtoName,"Status",status);
    }
return(hContact);
}

#include "mrim_userinfo.c"
#include "mrim_do_changestatus.c"
#include "mrim_listen.c"

//=======================================================
// Get Protocol Capabilities
//=======================================================
int MRIM_GetCaps(WPARAM wParam,LPARAM lParam)
{
if(wParam==PFLAGNUM_1)
    return(PF1_IM | PF1_ADDSEARCHRES | PF1_MODEMSG | PF1_SEARCHBYEMAIL |
           PF1_SEARCHBYNAME | PF1_NUMERICUSERID | PF1_AUTHREQ | PF1_CONTACT |
           PF1_VISLIST | PF1_INVISLIST);
if(wParam==PFLAGNUM_2)
    return(PF2_ONLINE | PF2_SHORTAWAY| PF2_INVISIBLE); // add the possible statuses here.
if(wParam==PFLAGNUM_3)
    return(0);//return(PF2_ONLINE | PF2_SHORTAWAY);
if(wParam==PFLAGNUM_4)
    return(PF4_SUPPORTTYPING);
return(0);
}

//=======================================================
// Get Protocol Name
//=======================================================
int MRIM_GetName(WPARAM wParam,LPARAM lParam)
{
lstrcpyn((char*)lParam,ProtoName,wParam);
return 0;
}

//=======================================================
//BPLoadIcon
//=======================================================
int MRIM_BPLoadIcon(WPARAM wParam,LPARAM lParam)
{
UINT id;

switch(wParam&0xFFFF)
    {
    case PLI_PROTOCOL:
        id = IDI_MAIN;
        break;
    case PLI_ONLINE:
        id = IDI_ONLINE;
        break;
    case PLI_OFFLINE:
        id = IDI_OFFLINE;
        break;
//    case PLI_AWAY:
//        break;
    default:
        return (int)(HICON)NULL;   
    }
return((int)LoadImage(HInstance,MAKEINTRESOURCE(id),IMAGE_ICON,GetSystemMetrics(wParam&PLIF_SMALL?SM_CXSMICON:SM_CXICON),GetSystemMetrics(wParam&PLIF_SMALL?SM_CYSMICON:SM_CYICON),0));
}

#include "mrim_do_hello.c"
#include "mrim_do_login.c"

unsigned long MRIM_do_authorize(unsigned char *email)
{
unsigned long seq;
static struct
    {
    mrim_packet_header_t hdr;
    unsigned char buf[1024];
    }packet;

packet.hdr.magic = CS_MAGIC;
packet.hdr.proto = PROTO_VERSION;
packet.hdr.seq = seq = GetSequenceNext();
packet.hdr.msg = MRIM_CS_AUTHORIZE;
packet.hdr.dlen = 0;
packet.hdr.from = 0;
packet.hdr.fromport = 0;

//MessageBox(NULL,"MRIM_do_authorize() called","Info",MB_OK|MB_ICONINFORMATION);
MRIM_Packet_AddString(&packet,email);
if(MRIM_sendpacket(&packet) == 0)
    {
    return(0);
    }
return(1);
}

unsigned long MRIM_do_list_delete(unsigned char *email,unsigned long id)
{
static struct
    {
    mrim_packet_header_t hdr;
    unsigned char parameters[4096];
    }packet;
unsigned long tmpdw;
unsigned long seq;

    // UL id
    // UL flags - same as for MRIM_CS_ADD_CONTACT
    // UL group id (unused if contact is group)
    // LPS contact
    // LPS name
packet.hdr.magic = CS_MAGIC;
packet.hdr.proto = PROTO_VERSION;
packet.hdr.seq = seq = GetSequenceNext();
packet.hdr.msg = MRIM_CS_MODIFY_CONTACT;
packet.hdr.dlen = 0;
packet.hdr.from = 0;
packet.hdr.fromport = 0;

MRIM_Packet_AddLong(&packet,id);//id
MRIM_Packet_AddLong(&packet,CONTACT_FLAG_REMOVED);//flags
MRIM_Packet_AddLong(&packet,0);//group
MRIM_Packet_AddString(&packet,email);
MRIM_Packet_AddString(&packet,email);
MRIM_Packet_AddLong(&packet,0);//??

//CODEBLOCK
//    {
//    unsigned char buf[4096];
//    DumpMemToBuffer(buf,&packet,packet.hdr.dlen+sizeof(mrim_packet_header_t));
//    MessageBox(NULL,buf,"Dump",MB_OK);
//    }
if(MRIM_sendpacket(&packet) == 0)
    {
    if(MRIM_receivepacket(&packet,sizeof(packet),seq,MRIM_GetTimeout()) == 0)
        {
        if(packet.hdr.msg == MRIM_CS_MODIFY_CONTACT_ACK)
            {
            unsigned long tmppos = 0;
            MRIM_Packet_GetLong(&tmppos,&packet,&tmpdw);// status
            //sprintf(packet.parameters,"%lu",tmpdw);
            //MessageBox(NULL,packet.parameters,"status",MB_OK);
            if(tmpdw == CONTACT_OPER_SUCCESS)
                return(0);
            }
        }
    }
return(1);
}

unsigned long MRIM_do_list_add(unsigned char *email,unsigned long *number)
{
static struct
    {
    mrim_packet_header_t hdr;
    unsigned char parameters[4096];
    }packet;
unsigned long tmpdw;
unsigned long seq;

packet.hdr.magic = CS_MAGIC;
packet.hdr.proto = PROTO_VERSION;
packet.hdr.seq = seq = GetSequenceNext();
packet.hdr.msg = MRIM_CS_ADD_CONTACT;
packet.hdr.dlen = 0;
packet.hdr.from = 0;
packet.hdr.fromport = 0;

MRIM_Packet_AddLong(&packet,0);//flags
MRIM_Packet_AddLong(&packet,0);//group
MRIM_Packet_AddString(&packet,email);
MRIM_Packet_AddString(&packet,email);
MRIM_Packet_AddLong(&packet,0);//??

if(MRIM_sendpacket(&packet) == 0)
    {
    if(MRIM_receivepacket(&packet,sizeof(packet),seq,MRIM_GetTimeout()) == 0)
        {
        if(packet.hdr.msg == MRIM_CS_ADD_CONTACT_ACK)
            {
            unsigned long tmppos = 0;
            MRIM_Packet_GetLong(&tmppos,&packet,&tmpdw);// status
            if(tmpdw == CONTACT_OPER_SUCCESS)//||(tmpdw == CONTACT_OPER_USER_EXISTS))
                {
                if(MRIM_Packet_GetLong(&tmppos,&packet,&tmpdw) == 0)// contact number
                    {
                    //sprintf(packet.parameters,"%lu",tmpdw);
                    //MessageBox(NULL,packet.parameters,"contact number",MB_OK);
                    (*number) = tmpdw;
                    return(0);
                    }
                }
            }
        }
    }
return(1);
}

#include "mrim_online.c"
//=======================================================
//SetStatus
//=======================================================
int MRIM_SetStatus(WPARAM wParam,LPARAM lParam)
{
int oldStatus;
oldStatus = MRIM_Status;

//ID_STATUS_ONLINE
//ID_STATUS_AWAY
//ID_STATUS_DND
//ID_STATUS_NA
//ID_STATUS_OCCUPIED
//ID_STATUS_FREECHAT
//ID_STATUS_INVISIBLE
//ID_STATUS_ONTHEPHONE
//ID_STATUS_OUTTOLUNCH
if((wParam == ID_STATUS_ONLINE)||(wParam == ID_STATUS_AWAY)||(wParam == ID_STATUS_INVISIBLE))
    {
    if(wParam != MRIM_Status)
        {
        MRIM_ConnectAndLogin(wParam);
        return(0);
        }
    }
else if(wParam == ID_STATUS_NA)
    {
    wParam = ID_STATUS_AWAY;
    if(wParam != MRIM_Status)
        {
        MRIM_ConnectAndLogin(wParam);
        return(0);
        }
    }
else if(wParam == ID_STATUS_OFFLINE)
    {
    if(wParam != MRIM_Status)
        {
        //MessageBox(NULL,"ID_STATUS_OFFLINE","MRIM_SetStatus() Called",MB_OK);
        MRIM_Status = wParam;
        ProtoBroadcastAck(ProtoName,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)oldStatus,wParam);
        Netlib_CloseHandle(MRIM_hServerPacketRecver);
        MRIM_hServerPacketRecver = NULL;
        Netlib_CloseHandle(MRIM_hServerConn);
        MRIM_hServerConn = NULL;
        MRIM_NewMessagesCount = 0;
        MAgent_OfflineAllContacts();
        return(0);
        }
    }
else{
//    if(wParam != MRIM_Status)
//        {
//        MessageBox(NULL,"unknown","change status",MB_OK);
//        MRIM_Status = wParam;
//        ProtoBroadcastAck(ProtoName,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)oldStatus,wParam);
//        }
    }
return(1);
}
//=======================================================
//GetStatus
//=======================================================
int MRIM_GetStatus(WPARAM wParam,LPARAM lParam)
{
if(MRIM_Status == ID_STATUS_ONLINE)return(ID_STATUS_ONLINE);
else if(MRIM_Status == ID_STATUS_AWAY)return(ID_STATUS_AWAY);
else if(MRIM_Status == ID_STATUS_INVISIBLE)return(ID_STATUS_INVISIBLE);
else return(ID_STATUS_OFFLINE);
}

#include "mrim_wd.c"

int MRIM_SearchByName(WPARAM wParam, LPARAM lParam)
{
//PROTOSEARCHBYNAME *psbn=(PROTOSEARCHBYNAME*)lParam;
unsigned long Sequence = 0;
//struct NWSearchByNameThreadParm *p;

//if((lParam != 0)&&(psbn->pszNick != NULL))
//    {
//    if((p=malloc(sizeof(struct NWSearchByNameThreadParm))) != NULL)
//        {
//        p->Flag = 0;
        Sequence = GetSequenceNext();
//        p->Sequence = Sequence;
//        p->NickName[0] = 0;
//        if((psbn->pszNick != NULL)&&(psbn->pszNick[0] != 0))
//            {
//            strncpy(p->NickName,psbn->pszNick,99);
//            }
// /       else if((psbn->pszFirstName != NULL)&&(psbn->pszFirstName[0] != 0))
//            {
//            strncpy(p->NickName,psbn->pszFirstName,99);
//            }
//        else if((psbn->pszLastName != NULL)&&(psbn->pszLastName[0] != 0))
//            {
//            strncpy(p->NickName,psbn->pszLastName,99);
//            }
//        p->NickName[99] = 0;
//        CharUpper(p->NickName);
//        if(_beginthread(NWSearchByNameThread,0,(void*)p) == 0)
//            {
//            free(p);
//            Sequence = 0;
//            }
//        }
//    }
return(Sequence);
}

struct MRIM_SearchByEmailThreadParm
    {
    unsigned long Sequence;
    unsigned long thid;
    unsigned char login[200];
    unsigned char domain[200];
    unsigned char email[400];
    struct
        {
        mrim_packet_header_t hdr;
        unsigned char parameters[4096];
        }packet;
    unsigned char buf[1024];
    PROTOSEARCHRESULT psr;
    };

unsigned long MRIM_SearchByEmailThread(void *parm)
{
struct MRIM_SearchByEmailThreadParm *p = parm;
unsigned long tmpdw;
unsigned long seq;

Sleep(200);
p->packet.hdr.magic = CS_MAGIC;
p->packet.hdr.proto = PROTO_VERSION;
p->packet.hdr.seq = seq = GetSequenceNext();
p->packet.hdr.msg = MRIM_CS_WP_REQUEST;
p->packet.hdr.dlen = 0;
p->packet.hdr.from = 0;
p->packet.hdr.fromport = 0;

MRIM_Packet_AddLong(&(p->packet),MRIM_CS_WP_REQUEST_PARAM_USER);
MRIM_Packet_AddString(&(p->packet),p->login);
MRIM_Packet_AddLong(&(p->packet),MRIM_CS_WP_REQUEST_PARAM_DOMAIN);
MRIM_Packet_AddString(&(p->packet),p->domain);

if(MRIM_sendpacket(&(p->packet)) == 0)
    {
    if(MRIM_receivepacket(&(p->packet),sizeof(p->packet),seq,MRIM_GetTimeout()) == 0)
        {
        if(p->packet.hdr.msg == MRIM_CS_ANKETA_INFO)
            {
            unsigned long tmppos = 0;
            unsigned long fields_num = 0;
            unsigned long t;
            MRIM_Packet_GetLong(&tmppos,&(p->packet),&tmpdw);// status
            if(tmpdw == MRIM_ANKETA_INFO_STATUS_OK)
                {
                MRIM_Packet_GetLong(&tmppos,&(p->packet),&fields_num);
                MRIM_Packet_GetLong(&tmppos,&(p->packet),&tmpdw);// max_rows
                MRIM_Packet_GetLong(&tmppos,&(p->packet),&tmpdw);// server_time
                for(t=0;t<fields_num;t++)
                    {//read filed names
                    MRIM_Packet_GetString(&tmppos,&(p->packet),p->buf);
                    //printf("%s\t",buf);
                    }
                //printf("\n");
                for(t=0;t<fields_num;t++)
                    {//read filed values
                    MRIM_Packet_GetString(&tmppos,&(p->packet),p->buf);
                    //printf("%s\t",buf);
                    }
                //printf("\n");
                p->psr.cbSize = sizeof(p->psr);
                p->psr.nick = p->email;
                p->psr.email = p->email;
                ProtoBroadcastAck(ProtoName,NULL,ACKTYPE_SEARCH,ACKRESULT_DATA,(HANDLE)(p->Sequence),(LPARAM)&(p->psr));
                }
            }
        }
    }
Sleep(100);
ProtoBroadcastAck(ProtoName,NULL,ACKTYPE_SEARCH,ACKRESULT_SUCCESS,(HANDLE)(p->Sequence),(LPARAM)"Ok.");
free(p);
return(0);
}

int MRIM_SearchByEmail(WPARAM wParam, LPARAM lParam)
{
//wParam=0
//lParam=(LPARAM)(char*)szEmail
//Returns a HANDLE to the search, or NULL on failure
unsigned char *email=(unsigned char *)lParam;
unsigned char *cptr;
unsigned long Sequence = 0;
struct MRIM_SearchByEmailThreadParm *p;

Sequence = GetSequenceNext();
if(lParam != 0)
    {
    if((cptr=strchr(email,'@')) != NULL)
        {
        if((p=malloc(sizeof(struct MRIM_SearchByEmailThreadParm))) != NULL)
            {
            p->Sequence = Sequence;
            strcpy(p->email,email);
            strcpy(p->login,email);
            cptr = strchr(p->login,'@');
            cptr[0] = 0;
            strcpy(p->domain,&(cptr[1]));
            CreateThread(NULL,0,(unsigned long (__stdcall *)(void *))MRIM_SearchByEmailThread,p,0,&(p->thid));
            }
        }
    }
return(Sequence);
}

int MRIM_AddToList(WPARAM wParam, LPARAM lParam)
{
unsigned long tmpdw = 0;

if(lParam != 0)
    {
    PROTOSEARCHRESULT *psr = (PROTOSEARCHRESULT*)lParam;

    if(psr->cbSize == sizeof(PROTOSEARCHRESULT))
        {
        HANDLE hContact;
        
        hContact = HContactFromEMail(psr->nick,1,1);
        DBWriteContactSettingByte(hContact,"CList","NotOnList",0);
        //DBDeleteContactSetting(hContact,"CList","Hidden");

        if(MRIM_do_list_add(psr->nick,&tmpdw) == 0)
            {
            DBWriteContactSettingDword(hContact,ProtoName,DB_SETTING_NUMBER,tmpdw);
            }
        return((int)hContact);
        }
    }
return(0);
}

#include "mrim_do_sendmessage.c"
#include "mrim_send.c"

#include "mrim_typing.c"

BOOL CALLBACK MRIM_EnterDetailsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
    {
    case WM_INITDIALOG:
        {
        DBVARIANT dbv;
            
        TranslateDialogDefault(hwndDlg);
        SendMessage(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM)LoadIcon(HInstance,MAKEINTRESOURCE(IDI_MAIN)));
            
        if(!DBGetContactSetting(NULL,ProtoName,DB_SETTING_EMAIL, &dbv))
            {
            SetDlgItemText(hwndDlg,IDC_EMAIL,dbv.pszVal);
            DBFreeVariant(&dbv);
            }
        if(!DBGetContactSetting(NULL,ProtoName,DB_SETTING_PASSWORD,&dbv))
            {
            CallService(MS_DB_CRYPT_DECODESTRING,strlen(dbv.pszVal)+1,(LPARAM)dbv.pszVal);
            SetDlgItemText(hwndDlg,IDC_PW,dbv.pszVal);
            DBFreeVariant(&dbv);
            }
        }
        break;
    case WM_CLOSE:
        EndDialog(hwndDlg, 0);
        break;
    case WM_COMMAND:
        switch(LOWORD(wParam))
            {
            case IDOK:
                {
                char str[128];

                GetDlgItemText(hwndDlg,IDC_EMAIL,str,sizeof(str));
                DBWriteContactSettingString(NULL,ProtoName,DB_SETTING_EMAIL,str);
                GetDlgItemText(hwndDlg,IDC_PW,str,sizeof(str));
                CallService(MS_DB_CRYPT_ENCODESTRING,sizeof(str),(LPARAM)str);
                DBWriteContactSettingString(NULL,ProtoName,DB_SETTING_PASSWORD,str);
                }
            case IDCANCEL:
                // Mark first run as completed
                //DBWriteContactSettingByte(NULL, pszICQProtoName, "FirstRun", 1);
                EndDialog(hwndDlg, IDCANCEL);
                break;
            }
        break;
    }
return(FALSE);
}
void MRIM_EnterDetails(void)
{
unsigned long flag = 0;
DBVARIANT dbv;

if(!DBGetContactSetting(NULL,ProtoName,DB_SETTING_EMAIL, &dbv))
    {
    DBFreeVariant(&dbv);
    if(!DBGetContactSetting(NULL,ProtoName,DB_SETTING_PASSWORD, &dbv))
        {
        DBFreeVariant(&dbv);
        flag = 1;
        }
    }

if(flag == 0)
    {
    DialogBox(HInstance,MAKEINTRESOURCE(IDD_MRIMACCOUNT),NULL,MRIM_EnterDetailsDlgProc);
    }
}

#include "mrim_do_modify.c"
#include "mrim_apparent.c"
#include "mrim_newmail.c"

#include "mrim_options.c"
#include "mrim_auth.c"
#include "mrim_info.c"

int MRIM_ContactModifyHook_nametoserver(HANDLE hContact)
{
int retval = 1;
DBVARIANT v_email;
DBVARIANT v_name;
DBCONTACTGETSETTING cgs;
unsigned long num;
unsigned long flags;

if(hContact != NULL)
    {
    cgs.szModule = ProtoName;
    cgs.szSetting = DB_SETTING_EMAIL;
    cgs.pValue = &v_email;
    if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs) == 0)
        {
        cgs.szModule = DB_SETTING_CLIST;
        cgs.szSetting = DB_SETTING_CLIST_MYHANDLE;
        cgs.pValue = &v_name;
        if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs) == 0)
            {
            if((num=DBGetContactSettingDword(hContact,ProtoName,DB_SETTING_NUMBER,0)) != 0)
                {
                flags = DBGetContactSettingDword(hContact,ProtoName,DB_SETTING_FLAGS,0);
                if(MRIM_do_modify(num,v_email.pszVal,flags,0,v_name.pszVal) == 0)
                    {
                    retval = 0;
                    }
                }
            DBFreeVariant(&v_name);
            }
        DBFreeVariant(&v_email);
        }
    }
return(retval);
}

int MRIM_ContactModifyHook(WPARAM wParam,LPARAM lParam)
{
//Called when a contact has had one of its settings changed
//  wParam=(WPARAM)(HANDLE)hContact
//  lParam=(LPARAM)(DBCONTACTWRITESETTING*)&dbcws
//typedef struct {
//    const char *szModule;   // pointer to name of the module that wrote the
//                            // setting to get
//    const char *szSetting;  // pointer to name of the setting to get
//    DBVARIANT value;        // variant containing the value to set
//} DBCONTACTWRITESETTING;
DBCONTACTWRITESETTING *dbcws = (DBCONTACTWRITESETTING*)lParam;
HANDLE hContact = (HANDLE)wParam;
char* szProto;

if((MRIM_Flag_ContactListReceiving == 0)&&(dbcws != NULL)&&(hContact != NULL))
    {
    if(strcmp(dbcws->szModule,DB_SETTING_CLIST) == 0)
        {
        if(strcmp(dbcws->szSetting,DB_SETTING_CLIST_MYHANDLE) == 0)
            {
            szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
            if((szProto != NULL)&&(strcmp(szProto,ProtoName) == 0))
                {// my contact deleted
                //MessageBox(NULL,"Called","MRIM_ContactRenamed()",MB_OK);
                //MessageBox(NULL,dbcws->szModule,"MRIM_ContactRenamed()",MB_OK);
                //MessageBox(NULL,dbcws->szSetting,"MRIM_ContactRenamed()",MB_OK);
                if(MRIM_ContactModifyHook_nametoserver(hContact) == 0)
                    {
                    }
                }
            }
        }
    }
return(0);
}

int MRIM_ContactDeletedHook(WPARAM wParam,LPARAM lParam)
{
HANDLE hContact = (HANDLE)wParam;
char* szProto;
DBVARIANT dbv;
DBCONTACTGETSETTING cgs;
unsigned long num;

szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
if((szProto != NULL)&&(strcmp(szProto,ProtoName) == 0))
    {// my contact deleted
    cgs.szModule = ProtoName;
    cgs.szSetting = DB_SETTING_EMAIL;
    cgs.pValue = &dbv;
    if(CallService(MS_DB_CONTACT_GETSETTING,wParam,(LPARAM)&cgs) == 0)
        {
        if((num=DBGetContactSettingDword(hContact,ProtoName,DB_SETTING_NUMBER,0)) != 0)
            {
            if(MRIM_do_list_delete(dbv.pszVal,num) == 0)
                {// delete ok
                //MessageBox(NULL,dbv.pszVal,"Contact Delete OK",MB_OK);
                }
            else{// delete failed
                //MessageBox(NULL,dbv.pszVal,"Contact Delete Failed",MB_OK);
                }
            }
        DBFreeVariant(&dbv);
        }
    }
return(0);
}

int MRIM_OptInit(WPARAM wParam, LPARAM lParam)
{
OPTIONSDIALOGPAGE odp = {0};
    
odp.cbSize = sizeof(odp);
odp.position = 0;
odp.hInstance = HInstance;
    
odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_MAGENT);
odp.pszGroup = Translate("Network");
odp.pszTitle = Translate(ProtoName);
odp.pfnDlgProc = MRIM_OptsDlgProc;
odp.flags = ODPF_BOLDGROUPS;
odp.nIDBottomSimpleControl = 0;//IDC_GROUP;
CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
    
return(0);
}
//=====================================================
// Name : __declspec(dllexport) PLUGININFO* MirandaPluginInfo
// Parameters: (DWORD mirandaVersion)
// Returns : 
// Description : Sets plugin info
//=====================================================

__declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
{
return(&pluginInfo);
}


BOOL WINAPI DllMain(HINSTANCE hinst,DWORD fdwReason,LPVOID lpvReserved)
{
HInstance = hinst;
return(TRUE);
}

int SystemModulesLoaded(WPARAM wParam,LPARAM lParam)
{
NETLIBUSER nlu = {0};

hHookOptInit = HookEvent(ME_OPT_INITIALISE,MRIM_OptInit);
hHookUserInfoInit = HookEvent(ME_USERINFO_INITIALISE,MRIM_OnDetailsInit);
hContactDeletedHook = HookEvent(ME_DB_CONTACT_DELETED,MRIM_ContactDeletedHook);
hContactModifyHook = HookEvent(ME_DB_CONTACT_SETTINGCHANGED,MRIM_ContactModifyHook);

//register netlib user
nlu.cbSize = sizeof(nlu);
nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS;
nlu.szDescriptiveName = ProtoName;
nlu.szSettingsModule = ProtoName;
hServerNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);

MAgent_OfflineAllContacts();

return(0);
}

int __declspec(dllexport)Load(PLUGINLINK *link)
{
PROTOCOLDESCRIPTOR pd;

pluginLink = link;


CODEBLOCK
    {
    unsigned char name[255];
    unsigned char *cptr;
    unsigned long t;

    GetModuleFileName(HInstance,name,253);
    if((cptr=strrchr(name,'\\')) == NULL)cptr = name;
    else cptr++;
    strcpy(name,cptr);
    if((cptr=strrchr(name,'.')) != NULL)cptr[0] = 0;
    //MessageBox(NULL,name,"name",MB_OK);
    strcat(ProtoName,name);
    //strcat(ProtoName,":");
    //strcat(ProtoName,"Mail.Ru.Agent");
    cptr = ProtoName;
    t = 0;
    while(cptr[0] != 0)
        {
        if(t >= 30)
            {
            cptr[0] = 0;
            break;
            }
        t++;
        cptr++;
        }
    }

#ifdef MRIM_DEBUG
    OpenDebugLog(ProtoName);
    PrintDebug("magent.c: Starting.\n");
#endif    

pd.cbSize=sizeof(pd);
pd.szName=ProtoName;
pd.type=PROTOTYPE_PROTOCOL;
CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd);

if(DBGetContactSettingDword(NULL,ProtoName,DB_SETTING_TIMEOUT,0) == 0)
    DBWriteContactSettingDword(NULL,ProtoName,DB_SETTING_TIMEOUT,10);
MRIM_EnterDetails();

HookEvent(ME_SYSTEM_MODULESLOADED,SystemModulesLoaded);

CODEBLOCK
    {
    DBCONTACTGETSETTING cgs;
    DBVARIANT dbv;

    cgs.szModule = ProtoName;
    cgs.szSetting = DB_SETTING_EMAIL;
    cgs.pValue = &dbv;
    if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)NULL,(LPARAM)(&cgs)) == 0)
        {
        DBWriteContactSettingString(NULL,ProtoName,"Nick",dbv.pszVal);
        #ifdef MRIM_DEBUG
            PrintDebug("Load: \"Nick\" (%s) is set.\n",dbv.pszVal);
        #endif
        DBFreeVariant(&dbv);
        }
    }

CODEBLOCK
    {
    CLISTMENUITEM mi;
    unsigned char buffer[100];
    strcpy(buffer,ProtoName);strcat(buffer,PS_GETCAPS);  CreateServiceFunction(buffer,MRIM_GetCaps);
    strcpy(buffer,ProtoName);strcat(buffer,PS_GETNAME);  CreateServiceFunction(buffer,MRIM_GetName);
    strcpy(buffer,ProtoName);strcat(buffer,PS_LOADICON); CreateServiceFunction(buffer,MRIM_BPLoadIcon);
    strcpy(buffer,ProtoName);strcat(buffer,PS_SETSTATUS);CreateServiceFunction(buffer,MRIM_SetStatus);
    strcpy(buffer,ProtoName);strcat(buffer,PS_GETSTATUS);CreateServiceFunction(buffer,MRIM_GetStatus);
//    strcpy(buffer,ProtoName);strcat(buffer,PS_SEARCHBYNAME); CreateServiceFunction(buffer,MRIM_SearchByName);
    strcpy(buffer,ProtoName);strcat(buffer,PS_SEARCHBYEMAIL); CreateServiceFunction(buffer,MRIM_SearchByEmail);
    strcpy(buffer,ProtoName);strcat(buffer,PS_ADDTOLIST); CreateServiceFunction(buffer,MRIM_AddToList);
//    strcpy(buffer,ProtoName);strcat(buffer,PSR_MESSAGE); CreateServiceFunction(buffer,MRIM_RecvMessage);
    strcpy(buffer,ProtoName);strcat(buffer,PSS_MESSAGE); CreateServiceFunction(buffer,MRIM_SendMessage);
    strcpy(buffer,ProtoName);strcat(buffer,PSS_USERISTYPING); CreateServiceFunction(buffer,MRIM_UserIsTyping);
    strcpy(buffer,ProtoName);strcat(buffer,PSS_SETAPPARENTMODE); CreateServiceFunction(buffer,MRIM_SetApparentMode);
//    strcpy(buffer,ProtoName);strcat(buffer,PSR_AUTH); CreateServiceFunction(buffer,MRIM_Authorization);

    strcpy(buffer,ProtoName);strcat(buffer,PSS_GETINFO); CreateServiceFunction(buffer,MRIM_GetInfo);
    strcpy(buffer,ProtoName);strcat(buffer,PS_AUTHALLOW); CreateServiceFunction(buffer,MRIM_AuthAllow);
    strcpy(buffer,ProtoName);strcat(buffer,PS_AUTHDENY);  CreateServiceFunction(buffer,MRIM_AuthDeny);
    strcpy(buffer,ProtoName);strcat(buffer,MS_REQ_AUTH);  CreateServiceFunction(buffer,MRIM_RequestAuthorization);
    ZeroMemory(&mi, sizeof(mi));
    mi.cbSize = sizeof(mi);
    mi.position = 1000030000;
    mi.flags = 0;
    mi.hIcon = NULL;
    mi.pszContactOwner = ProtoName;
    mi.pszName = Translate("Authorization..");
    strcpy(buffer,ProtoName);
    strcat(buffer,MS_REQ_AUTH);
    mi.pszService = buffer;
    hUserMenu = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi);
    }
    
CODEBLOCK
    {
    struct ListenThread_Data *p;
    if((p=(struct ListenThread_Data*)malloc(sizeof(struct ListenThread_Data))) != NULL)
        {
        CreateThread(NULL,0,(unsigned long (__stdcall *)(void *))ListenThread,p,0,&(p->thid));
        }
    }

CODEBLOCK
    {
    struct WatchDogThread_Data *p;
    if((p=(struct WatchDogThread_Data*)malloc(sizeof(struct WatchDogThread_Data))) != NULL)
        {
        CreateThread(NULL,0,(unsigned long (__stdcall *)(void *))WatchDogThread,p,0,&(p->thid));
        }
    }

CODEBLOCK
    {
    struct NewMailBoxMessagesThread_Data *p;
    if((p=(struct NewMailBoxMessagesThread_Data*)malloc(sizeof(struct NewMailBoxMessagesThread_Data))) != NULL)
        {
        CreateThread(NULL,0,(unsigned long (__stdcall *)(void *))NewMailBoxMessagesThread,p,0,&(p->thid));
        }
    }
return(0);
}

__declspec(dllexport)int Unload(void)
{
Netlib_CloseHandle(hServerNetlibUser);
if(hHookOptInit != NULL)UnhookEvent(hHookOptInit);
if(hContactDeletedHook != NULL)UnhookEvent(hContactDeletedHook);
if(hContactModifyHook != NULL)UnhookEvent(hContactModifyHook);
#ifdef MRIM_DEBUG
    PrintDebug("magent.c: Terminating.\n");
    CloseDebugLog();
#endif    
return(0);
}
