package kr.co.kihyun.beans.entity;



import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.NullValue;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import kr.co.kihyun.beans.entity.ecross.IRemotePersistable;
import kr.co.kihyun.io.IUploadable;
import javax.jdo.annotations.Serialized;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class TotReport extends AbstractPublicDocument implements IUploadable, IRemotePersistable {
	/**
	 *
	 */
	private static final long serialVersionUID = 8955275337415625177L;
	private static final Logger LOG = LoggerFactory.getLogger(TotReport.class);

	public static final String COL_DELIMITER = "!#";
	public static final String ROW_DELIMITER = "!%";
	public static final String TABLE_DELIMITER = "!`!";

	public static final int PROCESS_ACCEPT = TotReportProcess.ACCEPT.ordinal();
	public static final int PROCESS_REASSIGN = TotReportProcess.REASSIGN.ordinal();
	public static final int PROCESS_ASSIGN = TotReportProcess.ASSIGN.ordinal();
	public static final int PROCESS_RETURN = TotReportProcess.RETURN.ordinal();
	public static final int PROCESS_TEMP = TotReportProcess.TEMP.ordinal();
	public static final int PROCESS_APPROVE = TotReportProcess.APPROVE.ordinal();
	public static final int PROCESS_COMP = TotReportProcess.COMP.ordinal();
	public static final int PROCESS_END = TotReportProcess.END.ordinal();
	public static final int PROCESS_READ = TotReportProcess.READ.ordinal();
	public static final int PROCESS_CANCEL = TotReportProcess.CANCEL.ordinal();
	public static final int PROCESS_ALL = TotReportProcess.ALL.ordinal();
	public static final int PROCESS_NOT = TotReportProcess.NOT.ordinal();

    public static final int PROCESS_NOTE = TotReportProcess.NOTE.ordinal(); //자료회수

	public static final int TYPE_REPORT = TotReportType.REPORT.ordinal();
	public static final int TYPE_NOT_REPORT = TotReportType.NOT_REPORT.ordinal();
	public static final int TYPE_NOT_REPORT_REQ = TotReportType.NOT_REPORT_REQ.ordinal();

	public static final int RECOG_NOT = Recog.NOT_RECOG.ordinal();
	public static final int RECOG_PRSS = Recog.PRSS.ordinal();
	public static final int RECOG_COMP = Recog.COMP.ordinal();
	public static final int RECOG_RETURN = Recog.RETURN_RECOG.ordinal();
	public static final int RECOG_ARBITRARY = Recog.ARBITRARY.ordinal();
	public static final int RECOG_FINAL_RECOG = Recog.FINAL_RECOG.ordinal();

	@Persistent(nullValue = NullValue.EXCEPTION)
	private TotDoc totDoc;

	@Persistent
	private String acceptanceCode;

    @Persistent
	private String acptDoc;

	@Persistent(nullValue = NullValue.EXCEPTION)
	private Integer tableNum = 1;

	@Persistent
	private String num;

    /*@Persistent
	private String mDept;*/
    @Persistent
	private MDept mDept;

	@Persistent
	private String mUser;

	@Persistent(customValueStrategy = "timestamp")
	private Date regDate;

	@Persistent
	private Date submitDate;

	@Persistent
	private String data;

	@Persistent
	private String totData;

	@Persistent
    @Serialized
	private Map<String, List<Byte>> attachments;

	private String attachmentsPath;

	@Persistent
	private Integer appro = 0;

	@Persistent
	private Recog recog = Recog.NOT_RECOG;

	@Persistent
	private String note;

	@Persistent(nullValue = NullValue.EXCEPTION)
	private String isDeleted = "N"; // COLUMN: del_type

	@Persistent(nullValue = NullValue.EXCEPTION)
	private TotReportType type = TotReportType.REPORT; // COLUMN: type

	@Persistent(nullValue = NullValue.EXCEPTION)
	private TotReportProcess process = TotReportProcess.ACCEPT; // COLUMN: prss

	@Persistent
	private TotDoc slaveTotDoc; // COLUMN: down_doc_id

	@Persistent
	private TotDoc repTotDoc; // COLUMN: rep_doc_id

	@Persistent
	private AssignType assignType = AssignType.ASSIGN_TO_DEPT; // COLUMN: doc_type

	@Persistent(mappedBy = "totReport")
	private List<TotReportHistory> totReportHistories = new ArrayList<TotReportHistory>();

	@Persistent(mappedBy = "totReport")
	private List<Memo> memos = new ArrayList<Memo>();

	@Persistent(mappedBy = "totReport")
	private List<Repoadm> repoadms = new ArrayList<Repoadm>();

	@Persistent
	private Repoadm currentRepoadm = null;




		@Persistent(nullValue = NullValue.DEFAULT)
	private String secuYn = "N"; // COLUMN: secu_yn(보안문서여부), 기본값:N.비보안

    private String fileCheck = "N"; // COLUMN: file_check(파일첨부여부 확인), 기본값:N.미첨부




	public TotReport(TotDoc totDoc, MDept dept) {
		this.setTotDoc(totDoc);
		this.setDept(dept);
	}

	public TotReport() {
	}

    public String getFileCheck() {
		return fileCheck;
	}

	public void setFileCheck(String fileCheck) {
		this.fileCheck = fileCheck;
	}

    public String getSecuYn() {
        return secuYn;
    }

    public void setSecuYn(String secuYn) {
        this.secuYn = secuYn;
    }

	public TotDoc getTotDoc() {
		return this.totDoc;
	}

	public final void setTotDoc(TotDoc doc) {
		this.totDoc = doc;
	}

	public final AcceptanceCode getAcceptanceCode() {
		try {
			if (acceptanceCode != null)
				return AcceptanceCode.valueOf(acceptanceCode);
			else
				return new AcceptanceCode(acceptanceCode, null);
		} catch (Exception e) {
			LOG.error("Unable to parse acceptance code for {}", acceptanceCode);
			return new AcceptanceCode(acceptanceCode, null);
		}
	}

	public final void setAcceptanceCode(AcceptanceCode acceptanceCode) {
		this.acceptanceCode = acceptanceCode == null ? null : acceptanceCode.toString();
	}
        //문서번호
    public final AcptDoc getActDoc() {
		try {
			if (acptDoc != null)
				return AcptDoc.valueOf(acptDoc);
			else
				return new AcptDoc(acptDoc, null);
		} catch (Exception e) {
			LOG.error("Unable to parse acptDoc code for {}", acptDoc);
			return new AcptDoc(acptDoc, null);
		}
	}

	public final void setAcptDoc(AcptDoc acptDoc) {
		this.acptDoc = acptDoc == null ? null : acptDoc.toString();
	}

	public int getTableNum() {
		return this.tableNum;
	}

	public void setTableNum(int num) {
		this.tableNum = num;
	}

	public String getNum() {
		return this.num;
	}

	public void setNum(String num) {
		this.num = num;
	}

	public String getDept() {
		return this.mDept.getId();
	}

	public MDept getDept(PersistenceManager pm) {
	try {
			//LOG.debug("mDept: {}", this.mDept);
			return pm.getObjectById(MDept.class, this.mDept.getId());
		} catch (JDOObjectNotFoundException jonfe) {
			return null;
		}
	}

	public final void setDept(MDept mDept) {
		if (mDept == null)
			this.mDept = null;
		else
			this.mDept = mDept;
	}

	public MUser getUser(PersistenceManager pm) {
		try {
			return pm.getObjectById(MUser.class, this.mUser);
		} catch (JDOObjectNotFoundException jonfe) {
			MUser nullUser = new MUser();
			nullUser.setId(this.mUser);
			return nullUser;
		}
	}

    public String getUser()
    {
            return mUser;
        }

	public void setUser(MUser mUser) {
		if (mUser == null) {
			this.mUser = null;
			setOwnerEmail(null);
			setOwnerName(null);
			setOwnerPhone(null);
		} else {
			this.mUser = mUser.getId();
			setOwnerEmail(mUser.getEmail());
			setOwnerName(mUser.getEncName());
			setOwnerPhone(mUser.getPhone());
		}
	}

	public Date getRegDate() {
		return this.regDate == null ? null : new Date(this.regDate.getTime());
	}

	public void setRegDate(Date regDate) {
		this.regDate = regDate == null ? null : new Date(regDate.getTime());
	}

	public Date getSubmitDate() {
		return this.submitDate == null ? null : new Date(this.submitDate.getTime());
	}

	public void setSubmitDate(Date submitDate) {
		this.submitDate = submitDate == null ? null : new Date(submitDate.getTime());
	}

	public String getData() {
		return this.data;
	}

	public void setData(String data) {
		this.data = data;
	}

	public String getTotData() {
		return this.totData;
	}

	public void setTotData(String data) {
		this.totData = data;
	}

	@Override
	public Map<String, List<Byte>> getAttachments() {
		if (this.attachments == null)
			return Collections.unmodifiableMap(new HashMap<String, List<Byte>>());
		else
			return Collections.unmodifiableMap(attachments);
	}

	@Override
	public void addAttachment(String key, List<Byte> value) {
		if (this.attachments == null )
			this.attachments = new HashMap<String, List<Byte>>();
		this.attachments.put(key, value);
	}

	@Override
	public List<Byte> removeAttachment(String key) {
		return this.attachments.remove(key);
	}

    public void clearAttachment()
    {
        if(this.attachments==null) return;
        this.attachments.clear();
        this.attachments=null;
    }

    public String getAttachmentsPath(){
    	return this.attachmentsPath;
    }

    public void setAttachmentsPath(String attachmentsPath){
    	this.attachmentsPath = attachmentsPath;
    }

	public int getAppro() {
		return this.appro;
	}

	public void setAppro(int a) {
		this.appro = a;
	}

	public Recog getRecog() {
		return this.recog;
	}

	public void setRecog(Recog r) {
		this.recog = r;
	}

	public String getNote() {
		return this.note;
	}

	public void setNote(String note) {
		this.note = note;
	}

	public String isDeleted() {
		return this.isDeleted;
	}

	public void setDeleted(String isDeleted) {
		this.isDeleted = isDeleted;
	}

	public TotReportType getType() {
		return this.type;
	}

	public void setType(TotReportType t) {
		this.type = t;
	}

	public TotReportProcess getProcess() {
		return this.process;
	}

	public void setProcess(TotReportProcess p) {
		if (p.ordinal() < TotReportProcess.COMP.ordinal())
			this.setSubmitDate(null);
		else if (p == TotReportProcess.COMP)
			this.setSubmitDate(new Date());

		if (p == TotReportProcess.RETURN && this.getSlaveTotDoc() != null)	// NEIS-57
			this.process = TotReportProcess.TEMP;
		else
			this.process = p;
	}

	public TotDoc getSlaveTotDoc() {
		return this.slaveTotDoc;
	}

	public void setSlaveTotDoc(TotDoc doc) {
		this.slaveTotDoc = doc;
	}

	public TotDoc getRepTotDoc() {
		return this.repTotDoc;
	}

	public void setRepTotDoc(TotDoc doc) {
		this.repTotDoc = doc;
	}

	public AssignType getAssignType() {
		return this.assignType;
	}

	public void setAssignType(AssignType t) {
		this.assignType = t;
	}

	public void addHistory(TotReportHistory history) {
		this.totReportHistories.add(history);
	}

	public void removeHistory(TotReportHistory history) {
		this.totReportHistories.remove(history);
	}

	public List<TotReportHistory> getHistories() {
		return Collections.unmodifiableList(totReportHistories);
	}

	public void addMemo(Memo memo) {
		this.memos.add(memo);
	}

	public void removeMemo(Memo memo) {
		this.memos.remove(memo);
	}

	public List<Memo> getMemos() {
		return Collections.unmodifiableList(memos);
	}

	public void setRepoadms(List<Repoadm> repoadms) {
		this.repoadms = repoadms;
	}

	public List<Repoadm> getRepoadms() {
		return repoadms;
	}

	public void setCurrentRepoadm(Repoadm currentRepoadm) {
		this.currentRepoadm = currentRepoadm;
	}

	public Repoadm getCurrentRepoadm() {
		return currentRepoadm;
	}

	public TotReportHistory getRecentHistory() {
		TotReportHistory recentHistory = null;
		if (!this.getHistories().isEmpty())
			recentHistory = this.getHistories().get(this.getHistories().size() - 1);
		return recentHistory;
	}

	public int getRowCount() {
		return (getData().length() - getData().replaceAll(ROW_DELIMITER, "").length()) / ROW_DELIMITER.length();
	}

	@Override
	public String toString() {
		List<String> fieldList = new ArrayList<String>();
		if (totDoc != null)
			fieldList.add(totDoc.toString());
		if (mDept != null)
			fieldList.add(mDept.toString());
		if (mUser != null)
			fieldList.add(mUser.toString());
		if (slaveTotDoc != null)
			fieldList.add("slaveTotDoc::" + slaveTotDoc);
		if (repTotDoc != null)
			fieldList.add("repTotDoc::" + repTotDoc);
		StringBuilder str = new StringBuilder(100).append(super.toString()).append(fieldList);
		return str.toString();
	}

	@Override
	public MDept getOwnerParty(PersistenceManager pm) {
		return this.getDept(pm).getRootDept(pm);
	}

}
