package com.agilex.vamf.missionhealth.datalayer;

import com.agilex.vamf.missionhealth.domain.MissionReadinessReport;
import com.agilex.vamf.missionhealth.domain.WeeklyServiceMetrics;
import com.agilex.vamf.missionhealth.service.*;
import com.agilex.vamf.utils.DateHelper;
import com.agilex.vamf.utils.StringUtil;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.bson.types.ObjectId;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: vguthrie
 * Date: 11/15/13
 * Time: 11:13 AM
 */
public class MissionHealthWeeklyStatusTranslator extends MissionHealthTranslator {

    private static final String CREATE_DATETIME = "createDatetime";
    private static final String START_DATETIME = "startDatetime";
    private static final String COMPLETE_DATETIME = "completeDatetime";
    private static final String COMPLETE = "complete";
    private static final String STATUS = "status";
    private static final String ERRORS = "errors";
    private static final String DETAIL_RECORDS_UPDATED = "detailRecordsUpdated";
    private static final String USERS_WITH_LOGIN = "usersWithLogin";
    private static final String TOTAL_LOGINS = "totalLogins";
    private static final String SERVICE_METRICS = "serviceMetrics";
    private static final String USER_METRICS = "userMetrics";
    private static final String SERVICE = "service";
    private static final String TOTAL_USERS = "totalUsers";
    private static final String ACTIVE_USERS = "activeUsers";
    private static final String TOTAL_MISSIONS_COMPLETED = "totalMissionsCompleted";
    private static final String TOTAL_POINTS = "totalPoints";
    private static final String ANNUAL_SERVICE_METRICS="annualServiceMetrics";
    private static final String TOTAL_TROOPS="totalTroops";
    private static final String NOTIFICATION_TYPE="notificationType";

    public DBObject translateStatus(AbstractMissionHealthStatus abstractMissionHealthStatus){
        DBObject dbStatus = new BasicDBObject();
        if(null!=abstractMissionHealthStatus.getId())
            dbStatus.put(MONGO_ID, new ObjectId(abstractMissionHealthStatus.getId()));
        dbStatus.put(START_DATETIME, DateHelper.formatDateTimeInVistaFormat(abstractMissionHealthStatus.getStartDatetime()));
        dbStatus.put(CREATE_DATETIME, DateHelper.formatDateTimeInVistaFormat(abstractMissionHealthStatus.getCreateDatetime()));
        if(null!=abstractMissionHealthStatus.getCompleteDatetime())
            dbStatus.put(COMPLETE_DATETIME, DateHelper.formatDateTimeInVistaFormat(abstractMissionHealthStatus.getCompleteDatetime()));
        dbStatus.put(COMPLETE, abstractMissionHealthStatus.isComplete());
        dbStatus.put(STATUS, abstractMissionHealthStatus.getStatus());
        if(null!=abstractMissionHealthStatus.getErrors()){
            BasicDBList errorsList = new BasicDBList();
            for(String error : abstractMissionHealthStatus.getErrors()){
                errorsList.add(error);
            }
            dbStatus.put(ERRORS, errorsList);
        }
        return dbStatus;
    }

    public DBObject translateMissionHealthWeeklyStatus(MissionHealthWeeklyStatus missionHealthWeeklyStatus){
        DBObject dbMissionHealthWeeklyStatus = translateStatus(missionHealthWeeklyStatus);

        dbMissionHealthWeeklyStatus.put(DETAIL_RECORDS_UPDATED, missionHealthWeeklyStatus.getDetailRecordsUpdated());
        dbMissionHealthWeeklyStatus.put(USERS_WITH_LOGIN, missionHealthWeeklyStatus.getUsersWithLogin());
        dbMissionHealthWeeklyStatus.put(TOTAL_LOGINS, missionHealthWeeklyStatus.getTotalLogins());
        dbMissionHealthWeeklyStatus.put(TOTAL_MISSIONS_COMPLETED, missionHealthWeeklyStatus.getTotalMissionsCompleted());
        dbMissionHealthWeeklyStatus.put(SERVICE_METRICS, missionHealthWeeklyStatus.getServiceMetrics());
        if(null!=missionHealthWeeklyStatus.getServiceMetrics()){
            BasicDBList serviceMetricsList = new BasicDBList();
            for(WeeklyServiceMetrics serviceMetrics : missionHealthWeeklyStatus.getServiceMetrics()){
                serviceMetricsList.add(translateWeeklyServiceMetrics(serviceMetrics));
            }
            dbMissionHealthWeeklyStatus.put(SERVICE_METRICS, serviceMetricsList);
        }
        if(null!=missionHealthWeeklyStatus.getAnnualServiceMetrics()){
            BasicDBList annualServiceMetricsList = new BasicDBList();
            for(WeeklyServiceMetrics annualServiceMetrics : missionHealthWeeklyStatus.getAnnualServiceMetrics()){
                annualServiceMetricsList.add(translateWeeklyServiceMetrics(annualServiceMetrics));
            }
            dbMissionHealthWeeklyStatus.put(ANNUAL_SERVICE_METRICS, annualServiceMetricsList);
        }
        return dbMissionHealthWeeklyStatus;
    }

    private DBObject translateWeeklyServiceMetrics(WeeklyServiceMetrics weeklyServiceMetrics){
        DBObject dbObject = new BasicDBObject();
        dbObject.put(SERVICE, weeklyServiceMetrics.getService());
        dbObject.put(TOTAL_USERS, weeklyServiceMetrics.getTotalUsers());
        dbObject.put(ACTIVE_USERS, weeklyServiceMetrics.getActiveUsers());
        dbObject.put(TOTAL_MISSIONS_COMPLETED, weeklyServiceMetrics.getTotalMissionsCompleted());
        dbObject.put(TOTAL_POINTS, weeklyServiceMetrics.getTotalPoints());
        dbObject.put(TOTAL_TROOPS, weeklyServiceMetrics.getTotalTroops());
        return dbObject;
    }

    public DBObject translateWeeklyUserMetrics(WeeklyUserMetrics weeklyUserMetrics){
        DBObject dbObject = new BasicDBObject();
        dbObject.put(PATIENT_ID, weeklyUserMetrics.getPatientId());
        dbObject.put(CREATE_DATETIME, weeklyUserMetrics.getCreateDatetime());
        dbObject.put(TOTAL_LOGIN_DAYS_FOR_CYCLE, weeklyUserMetrics.getDaysWithLoginForCycle());
        dbObject.put(MISSION_READINESS_RPTS, populateMissionReadinessReportsDbList(weeklyUserMetrics.getMissionReadinessReportList()));
        return dbObject;
    }

    public DBObject translateNotificationStatus(MissionHealthNotificationStatus missionHealthNotificationStatus){
        DBObject dbNotificationStatus = translateStatus(missionHealthNotificationStatus);
        dbNotificationStatus.put(NOTIFICATION_TYPE, missionHealthNotificationStatus.getNotificationType());
        return dbNotificationStatus;
    }

    public AbstractMissionHealthStatus translateToStatus(DBObject po, AbstractMissionHealthStatus status){
        status.setId(StringUtil.objectToString(po.get(MONGO_ID)));
        status.setCreateDatetime(DateHelper.parseVistaDateTime(StringUtil.objectToString(po.get(CREATE_DATETIME))));
        status.setStartDatetime(DateHelper.parseVistaDateTime(StringUtil.objectToString(po.get(START_DATETIME))));
        if(null!=po.get(COMPLETE_DATETIME))
            status.setCompleteDatetime(DateHelper.parseVistaDateTime(StringUtil.objectToString(po.get(COMPLETE_DATETIME))));
        status.setComplete(Boolean.valueOf(StringUtil.objectToString(po.get(COMPLETE))));
        status.setStatus(StringUtil.objectToString(po.get(STATUS)));
        BasicDBList dbErrorsList = (BasicDBList) po.get(ERRORS);
        List<String> errors = new ArrayList<String>();
        if(null != dbErrorsList){
            Iterator<Object> dbErrorsListIterator = dbErrorsList.listIterator();
            while(dbErrorsListIterator.hasNext()){
                errors.add(StringUtil.objectToString(dbErrorsListIterator.next()));
            }
        }
        status.setErrors(errors);
        return status;
    }

    public MissionHealthWeeklyStatus translateToMissionHealthWeeklyStatus(DBObject po){
        MissionHealthWeeklyStatus missionHealthWeeklyStatus = new MissionHealthWeeklyStatus();
        missionHealthWeeklyStatus = (MissionHealthWeeklyStatus)translateToStatus(po, missionHealthWeeklyStatus);
        missionHealthWeeklyStatus.setDetailRecordsUpdated(Integer.valueOf(StringUtil.objectToString(po.get(DETAIL_RECORDS_UPDATED))));
        missionHealthWeeklyStatus.setUsersWithLogin(Integer.valueOf(StringUtil.objectToString(po.get(USERS_WITH_LOGIN))));
        missionHealthWeeklyStatus.setTotalMissionsCompleted(Integer.valueOf(StringUtil.objectToString(po.get(TOTAL_MISSIONS_COMPLETED))));
        missionHealthWeeklyStatus.setTotalLogins(Integer.valueOf(StringUtil.objectToString(po.get(TOTAL_LOGINS))));
        BasicDBList dbServiceMetricsList = (BasicDBList) po.get(SERVICE_METRICS);
        List<WeeklyServiceMetrics> serviceMetrics = new ArrayList<WeeklyServiceMetrics>();
        if(null != dbServiceMetricsList){
            Iterator<Object> dbServiceMetricsListIterator = dbServiceMetricsList.listIterator();
            while(dbServiceMetricsListIterator.hasNext()){
                serviceMetrics.add(translateToWeeklyServiceMetrics((DBObject) dbServiceMetricsListIterator.next()));
            }
            missionHealthWeeklyStatus.setServiceMetrics(serviceMetrics);
        }
        BasicDBList dbAnnualServiceMetricsList = (BasicDBList) po.get(ANNUAL_SERVICE_METRICS);
        List<WeeklyServiceMetrics> annualServiceMetrics = new ArrayList<WeeklyServiceMetrics>();
        if(null != dbAnnualServiceMetricsList){
            Iterator<Object> dbAnnualServiceMetricsListIterator = dbAnnualServiceMetricsList.listIterator();
            while(dbAnnualServiceMetricsListIterator.hasNext()){
            	annualServiceMetrics.add(translateToWeeklyServiceMetrics((DBObject) dbAnnualServiceMetricsListIterator.next()));
            }
            missionHealthWeeklyStatus.setAnnualServiceMetrics(annualServiceMetrics);
        }
        return missionHealthWeeklyStatus;
    }

    private WeeklyServiceMetrics translateToWeeklyServiceMetrics(DBObject po){
        WeeklyServiceMetrics weeklyServiceMetrics = new WeeklyServiceMetrics();
        weeklyServiceMetrics.setService(StringUtil.objectToString(po.get(SERVICE)));
        weeklyServiceMetrics.setTotalUsers(Integer.valueOf(StringUtil.objectToString(po.get(TOTAL_USERS))));
        weeklyServiceMetrics.setActiveUsers(Integer.valueOf(StringUtil.objectToString(po.get(ACTIVE_USERS))));
        weeklyServiceMetrics.setTotalMissionsCompleted(Integer.valueOf(StringUtil.objectToString(po.get(TOTAL_MISSIONS_COMPLETED))));
        weeklyServiceMetrics.setTotalPoints(Integer.valueOf(StringUtil.objectToString(po.get(TOTAL_POINTS))));
        weeklyServiceMetrics.setTotalTroops(Integer.valueOf(StringUtil.objectToString(po.get(TOTAL_TROOPS))));
        return weeklyServiceMetrics;
    }

    public WeeklyUserMetrics translateToWeeklyUserMetrics(DBObject po){
        WeeklyUserMetrics weeklyUserMetrics = new WeeklyUserMetrics();
        weeklyUserMetrics.setPatientId(StringUtil.objectToString(po.get(PATIENT_ID)));
        weeklyUserMetrics.setCreateDatetime(DateHelper.parseDateTime(StringUtil.objectToString(po.get(CREATE_DATETIME))));
        weeklyUserMetrics.setDaysWithLoginForCycle(Integer.valueOf(StringUtil.objectToString(po.get(TOTAL_LOGIN_DAYS_FOR_CYCLE))));
        if (po.get(MISSION_READINESS_RPTS) != null) {
            List<MissionReadinessReport> missionReadinessReports = populateMissionReadinessReports((BasicDBList) po.get(MISSION_READINESS_RPTS));
            weeklyUserMetrics.setMissionReadinessReportList(missionReadinessReports);
        }
        return weeklyUserMetrics;
    }

    public MissionHealthNotificationStatus translateToNotificationStatus(DBObject po){
        MissionHealthNotificationStatus missionHealthNotificationStatus = new MissionHealthNotificationStatus();
        missionHealthNotificationStatus = (MissionHealthNotificationStatus)translateToStatus(po, missionHealthNotificationStatus);
        missionHealthNotificationStatus.setNotificationType(StringUtil.objectToString(po.get(NOTIFICATION_TYPE)));
        return missionHealthNotificationStatus;
    }
}
