#include "stdafx.h"
#include "EditGroupWindow.h"

#define STATUS(x) status.SetText(env.GetWideString("EditGroupWindow::status",x,_T(x)))

EditGroupWindow::EditGroupWindow()
{

}

EditGroupWindow::~EditGroupWindow()
{

}


int EditGroupWindow::Create(HWND parent)
{
	Load("EditGroupWindow");
	GroupName.Load("EditGroupWindow::GroupName");
	Description.Load("EditGroupWindow::Description");
	PublicEdit.Load("EditGroupWindow::PublicEdit");
	PublicView.Load("EditGroupWindow::PublicView");
	Members.Load("EditGroupWindow::Members");

	status.Load("EditGroupWindow::status");

	ok.Load("EditGroupWindow::ok");
	cancel.Load("EditGroupWindow::cancel");
	groupdelete.Load("EditGroupWindow::delete");

	StaticWindow::Create(parent);
	GroupName.Create(hWnd);
	Description.Create(hWnd,ES_MULTILINE);
	PublicEdit.Create(hWnd);
	PublicView.Create(hWnd);
	Members.Create(hWnd);

	ok.Create(hWnd);
	cancel.Create(hWnd);
	groupdelete.Create(hWnd);

	status.Create(hWnd,ES_LEFT|ES_READONLY);
	status.Disable();
	STATUS("DefaultStatus");

	TabOrder tab;
	tab.Add(GroupName);
	tab.Add(Description);
	tab.Add(PublicEdit);
	tab.Add(PublicView);
	tab.Add(Members);
	tab.Add(ok);
	tab.Add(cancel);
	tab.Add(groupdelete);
	tab.Commit();

	// finally request notifications for changes
	AddCustomNotification(bcGroup);
	return 1;
}

void EditGroupWindow::DeepRefresh(int groupId)
{
	record.GroupId = groupId;

	if(groupId==NullGroupId){
		GroupName.SetText(L"");
		Description.SetText(L"");
		PublicEdit.SetValue(0);
		PublicView.SetValue(1);
		Members.SetText(L"");

		STATUS("DefaultStatus");
	} else {
		db.GetCachedGroup(groupId,record);

		GroupName.SetText(record.GroupName);
		Description.SetText(record.Description);
		PublicEdit.SetValue(record.PublicEdit);
		PublicView.SetValue(record.PublicView);

		Vector<int> memberIds;
		db.GetGroupMembers(groupId,memberIds);
		int i;
		Members.SetText(L"");
		for(i=0;i<memberIds.length;i++){
			std::wstring member;
			db.GetCachedUsername(memberIds[i],member);
			Members.AppendText(member.data());
			Members.AppendText(L" ");
		}
	}


}

void EditGroupWindow::OnButton(HWND h)
{

	if(h==ok.hWnd){

		rpc.BeginTransaction();

		// construct the event record
		record.GroupName = GroupName.Data();
		if(record.GroupName.length()==0){
			STATUS("NeedGroupName");
			rpc.EndTransaction();
			return;
		}
		record.Description = Description.Data();
		record.PublicEdit = PublicEdit.checked;
		record.PublicView = PublicView.checked;
		
		int tmpId;
		db.GetGroupId(record.GroupName,tmpId);

		// now ask the db layer to create/edit it
		if(tmpId!=record.GroupId && tmpId!=NullGroupId){
			STATUS("GroupNameExists");
			rpc.EndTransaction();
			return;
		}

		// update the subscription before modifying the rest
		STATUS("SubscribingMembers");
		DoEvents();
		// parse members and suscribe them
		std::wstring members = Members.Data();
		std::wstring member;
		int i,j = 0,len = members.length()+1;
		TCHAR * buffer = new TCHAR[len];
		_tcscpy(buffer,Members.Data());
		
		Vector<int> memberIds;
		int n = 0;
		memberIds.allocate(1000);
		for(i=0;i<len;i++){
			if(buffer[i]==L' ' || buffer[i]==L',' || buffer[i]==L'\0'){
				buffer[i] = L'\0';
				member = &(buffer[j]);
				j = i+1;

				if(member!=L""){
					print(L"Subscribing %s to the %s group.\n",member.data(),(TCHAR*)record.GroupName);
					db.GetUserId(member.data(),memberIds[n]);
					n++;
				} else {
					print(L"No such user: %s\n",member.data());
				}
			}
		}

		// unsubscribe all the old members that are not in the list
		db.SetGroupIdle(record.GroupId,1);
		Vector<int> oldmemberIds;
		db.GetGroupMembers(record.GroupId,oldmemberIds);
		for(i=0;i<oldmemberIds.length;i++){
			if(memberIds.find(oldmemberIds[i])==-1){
				db.UnsubscribeFromGroup(oldmemberIds[i],record.GroupId);
				rpc.ServerNotify(bcGroup,record.GroupId,bcUnsubscribe,oldmemberIds[i]);
			}
		}

		// now subscribe the new members
		for(i=0;i<n;i++){
			if(memberIds[i]!=NullUserId){
				if(oldmemberIds.find(memberIds[i])==-1){
					db.SubscribeToGroup(memberIds[i],record.GroupId);
					rpc.ServerNotify(bcGroup,record.GroupId,bcSubscribe,memberIds[i]);
				}
			} 
		}

		// now update the group
		STATUS("UpdatingGroup");
		DoEvents();
		db.UpdateGroup(record);
		rpc.ServerNotify(bcGroup,record.GroupId,bcModified,theApp.user.UserId);

		if(record.GroupId==NullGroupId){
			STATUS("UpdateFailed");
			rpc.EndTransaction();
			return;
		}

		// update the group list
		theApp.grouplist.DeepRefresh();
		theApp.grouplist.DeepRefreshEdit();

		// hide the window since we are done with it
		Hide();

		STATUS("DefaultStatus");

		rpc.EndTransaction();

	} else if(h==groupdelete.hWnd){
		rpc.BeginTransaction();

		// first unsubscribe everyone
		Vector<int> members;
		int i;

		db.GetGroupMembers(record.GroupId,members);
		for(i=0;i<members.length;i++){
			db.UnsubscribeFromGroup(members[i],record.GroupId);
			rpc.ServerNotify(bcGroup,record.GroupId,bcUnsubscribe,members[i]);
		}

		// then delete the group
		db.DeleteGroup(record.GroupId);
		rpc.ServerNotify(bcGroup,record.GroupId,bcRemove,theApp.user.UserId);
		// Update the group list
		ListItem * item = theApp.grouplist.list.GetItemByKey(record.GroupId);
		if(item){
			Group * group = (Group *)item->userdata;
			theApp.grouplist.Delete(group);
		}
		item = theApp.grouplist.editinglist.GetItemByKey(record.GroupId);
		if(item){
			Group * group = (Group *)item->userdata;
			theApp.grouplist.EditDelete(group);
		}	

		Hide();
		STATUS("DefaultStatus");

		rpc.EndTransaction();
	} else if(h==cancel.hWnd){
		Hide();

		STATUS("DefaultStatus");
	}
}

void EditGroupWindow::OnCustomNotify(int id, Notification& n)
{
	if(!hidden && record.GroupId!=NullGroupId && id==bcGroup && n.param[0]==record.GroupId){
		DeepRefresh(record.GroupId);
	}
}