package jp.agentec.abook.abv.bl.logic;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.TreeSet;

import jp.agentec.abook.abv.bl.acms.client.AcmsClient;
import jp.agentec.abook.abv.bl.acms.client.json.AcmsMessageJSON;
import jp.agentec.abook.abv.bl.acms.client.parameters.AcmsParameters;
import jp.agentec.abook.abv.bl.acms.client.parameters.AddMemberGroupParameters;
import jp.agentec.abook.abv.bl.common.exception.ABVException;
import jp.agentec.abook.abv.bl.common.exception.AcmsException;
import jp.agentec.abook.abv.bl.common.exception.NetworkDisconnectedException;
import jp.agentec.abook.abv.bl.common.log.Logger;
import jp.agentec.abook.abv.bl.data.dao.AbstractDao;
import jp.agentec.abook.abv.bl.data.dao.ContentDao;
import jp.agentec.abook.abv.bl.data.dao.ContentGroupDao;
import jp.agentec.abook.abv.bl.data.dao.GroupDao;
import jp.agentec.abook.abv.bl.data.dao.OperationDao;
import jp.agentec.abook.abv.bl.dto.ContentDto;
import jp.agentec.abook.abv.bl.dto.GroupDto;
import jp.agentec.adf.util.StringUtil;

public class GroupLogic extends AbstractLogic {
    private static final java.lang.String TAG = "GroupLogic";
    private GroupDao groupDao = AbstractDao.getDao(GroupDao.class);
	private ContentDao contentDao = AbstractDao.getDao(ContentDao.class);
    private OperationDao mOperationDao = AbstractDao.getDao(OperationDao.class);
	
	public Integer[] getServerUserGroupIds(String sid) throws NetworkDisconnectedException, ABVException {
		AcmsParameters param = new AcmsParameters(sid);
		return AcmsClient.getInstance(cache.getUrlPath(), networkAdapter).userGroup(param);
	}
	
	/**
	 * グループ情報をサーバから受信し、ローカルに保存します。既存のデータは上書きされます。また、サーバにないグループがローカルにある場合、そのグループは削除されます。
	 * @throws ABVException　キャッシュにユーザ情報がありません。再度ログインする必要があります。
	 * @throws AcmsException 
	 * @throws Exception その他、例外です。
	 * @since 1.0.0
	 */
	public List<GroupDto> fetchGroupsOnly() throws NetworkDisconnectedException, AcmsException {
		AcmsParameters param = new AcmsParameters(cache.getMemberInfo().sid);
		return AcmsClient.getInstance(cache.getUrlPath(), networkAdapter).group(param);
	}

	public void applyFetchedGroups(List<GroupDto> serverGroups) throws NetworkDisconnectedException, AcmsException {
		ContentGroupDao contentGroupDao = AbstractDao.getDao(ContentGroupDao.class);

		if (serverGroups == null || serverGroups.size() == 0) {
			Logger.w(TAG, "Group Data is Nothing");
			return;
		}
        try {
            groupDao.beginTransaction();

            boolean isChangedUserGroupInfo = false;
            List<GroupDto> localGroups = groupDao.getAllGroups();
            List<ContentDto> localContents = null;

            for (GroupDto serverDto : serverGroups) {
                boolean exist = false;

                //	ルートグループIDをキャッシュに入れておく
                if (serverDto.parentGroupId == 0) {
                    cache.refreshDefaultGroupId(serverDto.groupId);
                }

                if (localGroups != null) {
                    for (GroupDto localDto : localGroups) {
                        exist = serverDto.equals(localDto);

                        if (exist) {
                            //	update
                            groupDao.updateGroup(serverDto.groupId, serverDto.parentGroupId, serverDto.groupName, serverDto.groupLevel, serverDto.userGroupFlg, serverDto.groupCode);

                            //	更新したグループはローカルのリストから外しておく。
                            localGroups.remove(localDto);
                            break;
                        }
                    }
                }

                if (!exist) {
                    // ユーザの所属グループの情報が変更された
                    isChangedUserGroupInfo = true;
                    //	insert
                    groupDao.insertGroup(serverDto.groupId, serverDto.parentGroupId, serverDto.groupName, serverDto.groupLevel, serverDto.userGroupFlg, serverDto.groupCode);

                    if (localContents == null) {
                        localContents = contentDao.getAllContents();
                    }

                    if (localContents != null && localContents.size() > 0) {
                        for (ContentDto localDto : localContents) {
                            if (StringUtil.isNullOrEmpty(localDto.contentGroups)) {
                                continue;
                            }

                            String[] arrayContentGroup = localDto.contentGroups.split(",");
                            int groupsCount = arrayContentGroup.length;
                            for (int i = 0; i < groupsCount; i++) {
                                if (arrayContentGroup[i].equals(String.valueOf(serverDto.groupId))) {
                                    contentGroupDao.insertContentGroup(serverDto.groupId, localDto.contentId);
                                    break;
                                }
                            }
                        }
                    }
                    // グループ変更があった場合、全ての報告・回答タイプの同期フラグをtrueに設定
                    mOperationDao.updateNeedSyncForReportReplyType();
                }
            }

            if (localGroups != null) {
                for (GroupDto localDto : localGroups) {
                    //	delete
                    groupDao.deleteGroup(localDto, cache.getDefaultGroupId());
                    // ユーザの所属グループの情報が変更された
                    isChangedUserGroupInfo = true;
                }
            }

            groupDao.commit();
        } catch (Exception e) {
            groupDao.rollback();
            Logger.e("initializeGroups failed.", e);
            throw new RuntimeException(e);
        } finally {
        }
	}

	public void initializeGroups() throws NetworkDisconnectedException, AcmsException {
		applyFetchedGroups(fetchGroupsOnly());
	}
	
	//해당 콘텐츠 아이디를 가지고 있는 그룹정보
	public ArrayList<String>getExistContentsGroupInfo(long contentId) {
		List<GroupDto>groupDtoList = groupDao.getExistContentGroup(contentId);
		ArrayList<String>groupList = new ArrayList<String>();
		for (GroupDto groupDto : groupDtoList) {
			groupList.add(groupDto.groupName);
		}
		return groupList;
	}
	
	public Integer[] getLocalUserGroupIds() {
		List<GroupDto> userGroupList = groupDao.getUserGroups();
		TreeSet<Integer> userGroupIdSet = new TreeSet<Integer>();

		for (GroupDto groupDto : userGroupList) {
			userGroupIdSet.add(groupDto.groupId);
		}

		return userGroupIdSet.toArray(new Integer[userGroupIdSet.size()]);
	}
	
	public AcmsMessageJSON addMemberGroup(String groupName) throws AcmsException, NetworkDisconnectedException {
		AddMemberGroupParameters param = new AddMemberGroupParameters(cache.getMemberInfo().sid, groupName, Locale.getDefault().getLanguage());
		return AcmsClient.getInstance(cache.getUrlPath(), networkAdapter).addMemberGroup(param);
	}

}
