using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using TABS.MailCarrier.WebSDK.Calendar;
using Tabs = TABS.MailCarrier.WebSDK.Calendar;
using TABS.MailCarrier.WebSDK.User;

public partial class Calendar_Edit : System.Web.UI.Page
{
    const string DATE_FMT = "yyyy-MM-dd HH:mm";

    protected bool _new;            // 새 약속인지 여부
    protected Guid _calId;          // 일정표 ID
    private Guid _appId;          // 약속 ID
    private Guid _recurId;        // 되풀이 약속 ID
    private bool _recur;          // 되풀이 약속인지 여부
    protected string _sdate = "";   // 선택일자
    private McCalendar.RsAccessFlag _accessFlag;      // 사용 권한
    private bool _readable;       // 읽기 가능 여부
    private bool _writable;       // 쓰기 가능 여부
    private WebUser.LoginInfo _loginUser;

    protected string _FinishDate_defaultDate = "";
    protected string _BeginDateTime_defaultDate = "";
    protected string _EndDateTime_defaultDate = "";

    protected override void InitializeCulture()
    {
        string defLang = WebUser.CurrentUser.UiLanguage;
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(defLang);
        Thread.CurrentThread.CurrentUICulture = new CultureInfo(defLang);
        base.InitializeCulture();
    }

    protected void Page_Init(object sender, EventArgs e)
    {
        WebUtil.SetKendoUiLocalResource(Page.Header, WebUser.CurrentUser.UiLanguage);
        WebUtil.SetMcCommonCss(Page.Header);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        _new = (WebParam.GetStrParamValue("new") == "true");
        _calId = WebParam.GetGuidParamValue("cid");
        _appId = WebParam.GetGuidParamValue("appid");
        _recurId = WebParam.GetGuidParamValue("recurid");
        _recur = _recurId != Guid.Empty && WebParam.GetStrParamValue("appid") == "";
        _sdate = WebParam.GetStrParamValue("sdate");
        _loginUser = WebUser.CurrentUser;

        if (!IsPostBack)
        {
            Page.Title = AppSetting.GetTitleInfo(Request).Title;

            McCalendar calendar = new McCalendar(_calId);
            _accessFlag = McCalendar.GetAccessFlag(WebUser.CurrentUser.DomainUserID, _calId);
            _readable = (_accessFlag != McCalendar.RsAccessFlag.None);
            _writable = (_accessFlag & (McCalendar.RsAccessFlag.Write | McCalendar.RsAccessFlag.Admin)) > 0;
            ViewState["_accessFlag"] = _accessFlag;

            if (_new)
                NewAppointment();
            else
                LoadAppointment();

            // 개인 연락처만 미리 알림 정보가 유효하므로 공유 연락처의 경우 AlertPanel을 감춘다. -> Web push 알림 확장으로 공유도 미리 알림 편집 가능
            //BootstrapUtil.CollapseControl(AlertPanel, !calendar.IsMine(WebUser.CurrentUser.DomainUserID));

            if (!calendar.IsMine(WebUser.CurrentUser.DomainUserID))            
            {
                // 공유 일정표인 경우 알림 해제 불가, 참석자 지정 불가
                BootstrapUtil.CollapseCheckbox(AlertedCheckBoxDiv, true);
                BootstrapUtil.CollapseControl(AttendeePanel, true);
            }
            ViewState["_BeginDateTime_defaultDate"] = _BeginDateTime_defaultDate;
            ViewState["_EndDateTime_defaultDate"] = _EndDateTime_defaultDate;
            ViewState["_FinishDate_defaultDate"] = _FinishDate_defaultDate;
        }
        else
        {
            _accessFlag = (McCalendar.RsAccessFlag)ViewState["_accessFlag"];
            _readable = (_accessFlag != McCalendar.RsAccessFlag.None);
            _writable = (_accessFlag & (McCalendar.RsAccessFlag.Write | McCalendar.RsAccessFlag.Admin)) > 0;
            _BeginDateTime_defaultDate = (string)ViewState["_BeginDateTime_defaultDate"];
            _EndDateTime_defaultDate = (string)ViewState["_EndDateTime_defaultDate"];
            _FinishDate_defaultDate = (string)ViewState["_FinishDate_defaultDate"];
        }
    }

    protected void SaveButton_Click(object sender, EventArgs e)
    {
        if (_new)
        {
            SaveAppointment();
        }
        else
        {
            UpdateAppointment();
        }
    }

    #region Loading Appointment

    protected void InitAppointment()
    {
    }

    protected void InitRecurrence()
    {
        FinishButton1.Checked = true;
        _FinishDate_defaultDate = _loginUser.GetLocalToday().ToShortDateString();
        EverymonthButton1.Checked = true;
    }

    private void NewAppointment()
    {
        if (!_writable)
        {
            Response.Redirect("~/Error.aspx?code=17", true);        // 새 약속을 생성할 권한이 없습니다. 
        }

        InitRecurrence();

        DateTime selectedDate;
        if (!DateTime.TryParse(_sdate, out selectedDate))
        {
            selectedDate = WebUser.CurrentUser.GetLocalToday();
        }
        DateTime startTime = GetStartTime(selectedDate);
        DateTime endTime = startTime.AddMinutes(60);
        _BeginDateTime_defaultDate = startTime.ToString(DATE_FMT);
        _EndDateTime_defaultDate = endTime.ToString(DATE_FMT);

        if (WebParam.GetStrParamValue("allday") == "true")
        {
            AllDayCheckBox.Checked = true;
        }

        AlertCheckBox.Checked = true;           // 미리 알림 사용
        AlertMinList.SelectedIndex = 3;         // 15분전 알림
        AlertedCheckBox.Checked = false;
    }

    private void LoadAppointment()
    {
        InitAppointment();
        InitRecurrence();

        // 쓰기 권한이 없을 경우 UI 조정
        if (!_writable)
        {
            SaveButton.Visible = false;
        }

        // 읽기 권한 이상은 있어야 일정을 출력한다.
        if (!_readable)
        {
            Response.Redirect("~/Error.aspx?code=8", true);
            return;
        }

        if (!_recur)
        {
            if (_appId == Guid.Empty)
            {
                // 새 되풀이 예외 편집
                RecurrentAppointment appointment = new RecurrentAppointment(_recurId);
                appointment.Load();
                SubjectTextBox.Value = appointment.Subject;
                PlaceTextBox.Value = appointment.Place;
                BusyStatusList.SelectedValue = appointment.BusyStatus.ToString();
                MemoTextBox.Value = WebUtil.GetHtml4WebEditor(appointment.Memo);
                DateTime exceptTime, exBegin, exEnd;
                if (DateTime.TryParse(WebParam.GetStrParamValue("begin"), out exceptTime))
                {
                    TimeSpan ts = exceptTime - appointment.BeginTime;
                    exBegin = appointment.BeginTime.AddMinutes(ts.TotalMinutes);
                    exEnd = appointment.EndTime.AddMinutes(ts.TotalMinutes);
                }
                else
                {
                    exBegin = _loginUser.ToLocalTime(appointment.BeginTime);
                    exEnd = _loginUser.ToLocalTime(appointment.EndTime);
                }
                _BeginDateTime_defaultDate = exBegin.ToString(DATE_FMT);
                _EndDateTime_defaultDate = exEnd.ToString(DATE_FMT);

                AllDayCheckBox.Checked = (appointment.Type & Appointment.AppointmentType.AllDay) > 0;
                AlertCheckBox.Checked = (appointment.Type & Appointment.AppointmentType.Alert) > 0;
                AlertMinList.SelectedValue = appointment.AlertMinute.ToString();
                AlertedCheckBox.Checked = (appointment.Type & Appointment.AppointmentType.Alerted) > 0;
                if (!appointment.IsOriginMeetingRequest) DisableAttendeeInput();
                if (appointment.Attendees.Count > 0)
                {
                    AttendeeListView.DataSource = appointment.Attendees;
                    AttendeeListView.DataBind();
                }
            }
            else
            {
                Appointment appointment = new Appointment(_appId);
                appointment.Load();
                SubjectTextBox.Value = appointment.Subject;
                PlaceTextBox.Value = appointment.Place;
                MemoTextBox.Value = WebUtil.GetHtml4WebEditor(appointment.Memo);
                DateTime beginTime = appointment.BeginTime;
                DateTime endTime = appointment.EndTime;
                _BeginDateTime_defaultDate = beginTime.ToString(DATE_FMT);
                _EndDateTime_defaultDate = endTime.ToString(DATE_FMT);
                AllDayCheckBox.Checked = (appointment.Type & Appointment.AppointmentType.AllDay) > 0;
                AlertCheckBox.Checked = (appointment.Type & Appointment.AppointmentType.Alert) > 0;
                AlertMinList.SelectedValue = appointment.AlertMinute.ToString();
                AlertedCheckBox.Checked = (appointment.Type & Appointment.AppointmentType.Alerted) > 0;
                if (!appointment.IsOriginMeetingRequest) DisableAttendeeInput();
                if (appointment.Attendees.Count > 0)
                {
                    AttendeeListView.DataSource = appointment.Attendees;
                    AttendeeListView.DataBind();
                }

                // 일반 약속은 되풀이 Disable
                RecurList.Enabled = false;
            }
        }
        else
        {
            LoadRecurAppointment();
        }
    }

    protected void LoadRecurAppointment()
    {
        RecurrentAppointment appointment = new RecurrentAppointment(_recurId);
        appointment.Load();
        // 약속 내용 로드
        SubjectTextBox.Value = appointment.Subject;
        PlaceTextBox.Value = appointment.Place;
        MemoTextBox.Value = WebUtil.GetHtml4WebEditor(appointment.Memo);
        DateTime beginTime = appointment.BeginTime;
        DateTime endTime = appointment.EndTime;
        _BeginDateTime_defaultDate = beginTime.ToString(DATE_FMT);
        _EndDateTime_defaultDate = endTime.ToString(DATE_FMT);
        AllDayCheckBox.Checked = (appointment.Type & Appointment.AppointmentType.AllDay) > 0;
        AlertCheckBox.Checked = (appointment.Type & Appointment.AppointmentType.Alert) > 0;
        AlertMinList.SelectedValue = appointment.AlertMinute.ToString();
        AlertedCheckBox.Checked = (appointment.Type & Appointment.AppointmentType.Alerted) > 0;
        if (!appointment.IsOriginMeetingRequest) DisableAttendeeInput();
        if (appointment.Attendees.Count > 0)
        {
            AttendeeListView.DataSource = appointment.Attendees;
            AttendeeListView.DataBind();
        }

        RecurList.Items.RemoveAt(0);

        // 되풀이 종류에 따른 설정 값 로드
        switch (appointment.RecurType)
        {
            case RecurrentAppointment.RecurrentType.EveryDay:
                RecurList.SelectedValue = "1";
                EverydayIntervalList.SelectedValue = appointment.Recurrence.Interval.ToString();
                break;
            case RecurrentAppointment.RecurrentType.EveryWeek:
                RecurList.SelectedValue = "2";
                EveryweekList.SelectedValue = appointment.Recurrence.Interval.ToString();
                int dayOfWeek = appointment.Recurrence.DayOfWeek;
                if ((dayOfWeek & 1) > 0) WeekdayCheckBoxList1.Checked = true;
                if ((dayOfWeek & 2) > 0) WeekdayCheckBoxList2.Checked = true;
                if ((dayOfWeek & 4) > 0) WeekdayCheckBoxList3.Checked = true;
                if ((dayOfWeek & 8) > 0) WeekdayCheckBoxList4.Checked = true;
                if ((dayOfWeek & 16) > 0) WeekdayCheckBoxList5.Checked = true;
                if ((dayOfWeek & 32) > 0) WeekdayCheckBoxList6.Checked = true;
                if ((dayOfWeek & 64) > 0) WeekdayCheckBoxList7.Checked = true;
                break;
            case RecurrentAppointment.RecurrentType.EveryMonth:
                RecurList.SelectedValue = "3";
                EverymonthButton1.Checked = true;
                EverymonthIntervalList.SelectedValue = appointment.Recurrence.Interval.ToString();
                break;
            case RecurrentAppointment.RecurrentType.EveryMonthDay:
                RecurList.SelectedValue = "3";
                EverymonthButton2.Checked = true;
                MonthEveryList.SelectedValue = appointment.Recurrence.Interval.ToString();
                MonthOrderList.SelectedValue = appointment.Recurrence.WeekOfMonth.ToString(); ;
                MonthOrderWeekList.SelectedValue = appointment.Recurrence.DayOfWeek.ToString();
                break;
            case RecurrentAppointment.RecurrentType.EveryYear:
                RecurList.SelectedValue = "4";
                EveryyearIntervalList.SelectedValue = appointment.Recurrence.Interval.ToString();
                break;
            case RecurrentAppointment.RecurrentType.EveryYearDay:
                RecurList.SelectedValue = "4";
                EveryyearButton2.Checked = true;
                EveryyearIntervalList2.SelectedValue = appointment.Recurrence.Interval.ToString();
                EveryyearMonthList.SelectedValue = appointment.Recurrence.MonthOfYear.ToString();
                EveryyearOrderList.SelectedValue = appointment.Recurrence.WeekOfMonth.ToString();
                EveryyearWeekList.SelectedValue = appointment.Recurrence.DayOfWeek.ToString();
                break;
            default:
                RecurList.SelectedValue = "0";
                break;
        }

        //되풀이 종료일 로드
        switch (appointment.RecurrentFinish.Type)
        {
            case RecurrentFinish.FinishType.None:
                FinishButton1.Checked = true;
                break;
            case RecurrentFinish.FinishType.Occurrence:
                FinishButton2.Checked = true;
                FinishRecurCountTextBox.Value = appointment.RecurrentFinish.Occurrence.ToString();
                break;
            case RecurrentFinish.FinishType.Until:
                FinishButton3.Checked = true;
                DateTime dt = appointment.RecurrentFinish.Until;
                DateTime finishDate = new DateTime(dt.Year, dt.Month, dt.Day);
                _FinishDate_defaultDate = finishDate.ToShortDateString();
                break;
        }
    }

    protected DateTime GetStartTime(DateTime date)
    {
        DateTime now = WebUser.CurrentUser.GetLocalNow();
        DateTime newTime = date;
        if (newTime.Hour == 0)
        {
            int addMminutes = 0;
            if (now.Minute < 30) addMminutes = 30;
            else if (now.Minute <= 59) addMminutes = 60;

            newTime = newTime.AddHours(now.Hour);
            newTime = newTime.AddMinutes(addMminutes);
        }
        return newTime;
    }

    private void DisableAttendeeInput()
    {
        BootstrapUtil.CollapseControl(AttendeeInput, true);
    }

    #endregion

    #region Saving Appointment

    private void SaveAppointment()
    {
        // 쓰기 권한 검사
        McCalendar.RsAccessFlag accessFlag = McCalendar.GetAccessFlag(WebUser.CurrentUser.DomainUserID, _calId);
        if ((accessFlag & (McCalendar.RsAccessFlag.Write | McCalendar.RsAccessFlag.Admin)) == 0)
        {
            Response.Redirect("~/Error.aspx?code=0", true);
            return;
        }
        bool recur = RecurList.SelectedValue != "0";

        if (!recur)
        {
            // 약속을 추가한다.
            Appointment appointment = new Appointment();
            if (!GetAppointmentFromUI(appointment)) return;
            bool isMeetingRequest = (appointment.Attendees.Count > 0);
            if (isMeetingRequest)
            {
                appointment.Type |= Appointment.AppointmentType.MeetingRequest;
                appointment.MeetingStatus = Appointment.MeetingStatusType.IsMeeting;
            }

            McCalendar calendar = new McCalendar(_calId);
            calendar.AddAppointment(appointment);
            WebOperationLog.Write(WebUser.CurrentUser.MailAddress, Request.UserHostAddress, "M/Calendar/Edit.aspx", "AddApp", string.Format("CID:{0} AID:{1} S:{2}", _calId.ToString(), appointment.ID.ToString(), appointment.Subject));
            ShowSuccessMessage(GetLocalResourceObject("Msg08").ToString()); // 새 약속이 올바르게 생성되었습니다.

            // 참석자가 존재하는 경우 메일을 발송한다.
            if (isMeetingRequest)
            {
                MeetingRequest meetReq = new MeetingRequest(WebUser.CurrentUser.DomainUserID, WebUser.CurrentUser.Name, WebUser.CurrentUser.MailAddress);
                meetReq.SendRequestMail(appointment);
            }            
        }
        else
        {
            // 되풀이 약속을 추가한다.
            RecurrentAppointment appointment = new RecurrentAppointment();
            if (!GetRecurrentAppointmentFromUI(appointment)) return;
            string errMsg;
            if (appointment.ValidRecurrence(out errMsg))
            {
                bool isMeetingRequest = (appointment.Attendees.Count > 0);
                if (isMeetingRequest)
                {
                    appointment.Type |= Appointment.AppointmentType.MeetingRequest;
                    appointment.MeetingStatus = Appointment.MeetingStatusType.IsMeeting;
                }

                McCalendar calendar = new McCalendar(_calId);
                calendar.AddRecurrentAppointment(appointment);
                WebOperationLog.Write(WebUser.CurrentUser.MailAddress, Request.UserHostAddress, "M/Calendar/Edit.aspx", "AddRecur", string.Format("CID:{0} AID:{1} S:{2}", _calId.ToString(), appointment.ID.ToString(), appointment.Subject));
                ShowSuccessMessage(GetLocalResourceObject("Msg09").ToString());   // 새 되풀이 약속이 올바르게 생성되었습니다.

                if (appointment.Attendees.Count > 0)
                {
                    MeetingRequest meetReq = new MeetingRequest(WebUser.CurrentUser.DomainUserID, WebUser.CurrentUser.Name, WebUser.CurrentUser.MailAddress);
                    meetReq.SendRequestMail(appointment);
                }
            }
            else
            {
                ShowWarningMessage(errMsg);
            }
        }
    }

    /// <summary>
    /// UI 입력값으로 부터 약속 정보를 생성해서 반환한다.
    /// </summary>
    /// <returns></returns>
    private bool GetAppointmentFromUI(Appointment appointment)
    {
        DateTime beginTime, endTime;
        if (!DateTime.TryParse(Request["BeginDateTime"], out beginTime))
        {
            ShowWarningMessage(GetLocalResourceObject("Msg10").ToString());       // 잘못된 형식의 시작 날짜가 입력되었습니다.
            return false;
        }
        if (!DateTime.TryParse(Request["EndDateTime"], out endTime))
        {
            ShowWarningMessage(GetLocalResourceObject("Msg11").ToString());     // 잘못된 형식의 종료 날짜가 입력되었습니다.
            return false;
        }
        if (beginTime > endTime)
        {
            ShowWarningMessage(GetLocalResourceObject("Msg12").ToString());     // 시작 시각이 종료 시각 보다 앞서야 합니다.
            return false;
        }

        if (AllDayCheckBox.Checked)
        {
            // 하루 종일이 선택된 경우
            appointment.Type |= Appointment.AppointmentType.AllDay;
            beginTime = new DateTime(beginTime.Year, beginTime.Month, beginTime.Day);
            if (endTime.Hour == 0 && endTime.Minute == 0)
                endTime = new DateTime(endTime.Year, endTime.Month, endTime.Day);
            else
                endTime = new DateTime(endTime.Year, endTime.Month, endTime.Day).AddDays(1);
            if (beginTime >= endTime) endTime = beginTime.AddDays(1);
            appointment.BeginTime = beginTime;
            appointment.EndTime = endTime;
        }
        else
        {
            appointment.BeginTime = beginTime;
            appointment.EndTime = endTime;
        }
        if (AlertCheckBox.Checked)
        {
            // 미리 알림이 선택된 경우
            appointment.Type |= Appointment.AppointmentType.Alert;
        }
        if (AlertedCheckBox.Checked)
        {
            // 약속 확인이 선택된 경우
            appointment.Type |= Appointment.AppointmentType.Alerted;
        }
        appointment.AlertMinute = int.Parse(AlertMinList.SelectedValue);
        appointment.Subject = SubjectTextBox.Value;
        appointment.Place = PlaceTextBox.Value;
        appointment.OrganizerName = WebUser.CurrentUser.Name;
        appointment.OrganizerEmail = WebUser.CurrentUser.MailAddress;
        byte[] bytes = new byte[32];
        Guid.NewGuid().ToByteArray().CopyTo(bytes, 0);
        string hex = BitConverter.ToString(bytes);
        appointment.UID = hex.Replace("-", "");
        appointment.BusyStatus = (Appointment.BusyStatusType)int.Parse(BusyStatusList.SelectedValue);
        appointment.Memo = WebUtil.GetHtmlWithContainer(HttpUtility.HtmlDecode(MemoTextBox.Value));
        // 참석자 처리
        foreach (string item in Attendees.Value.Split(new char[] { ';' }))
        {
            if (item.Length > 0)
            {
                List<RcptItem> rcptItems = NewMsgUtil.GetRecipientByType(item, NewMsgUtil.MsgType.To, NewMsgUtil.MsgSource.Email);
                RcptItem rcptItem = rcptItems[0];
                if (rcptItem.Value != "")
                {
                    if (rcptItem.Name == "") rcptItem.Name = rcptItem.Value.Split('@')[0];  // 입력 항목에 이름이 없을 경우 메일 주소에서 계정 부분을 추출해 이름으로 사용
                    appointment.Attendees.Add(new Attendee(rcptItem.Value, rcptItem.Name, Attendee.AttendeeType.Optional, Attendee.AttendeeStatus.ResponseUnknown));
                }
            }
        }
        // 참석자에 자신의 계정이 존재할 경우 Remove
        Attendee attendee = appointment.Attendees.Find(WebUser.CurrentUser.MailAddress);
        if (attendee != null) appointment.Attendees.Remove(attendee);

        return true;
    }

    private bool GetRecurrentAppointmentFromUI(RecurrentAppointment appointment)
    {
        DateTime beginTime, endTime, date;
        if (!DateTime.TryParse(Request["BeginDateTime"], out beginTime))
        {
            ShowWarningMessage(GetLocalResourceObject("Msg10").ToString());       // 잘못된 형식의 시작 날짜가 입력되었습니다.
            return false;
        }
        if (!DateTime.TryParse(Request["EndDateTime"], out endTime))
        {
            ShowWarningMessage(GetLocalResourceObject("Msg11").ToString());     // 잘못된 형식의 종료 날짜가 입력되었습니다.
            return false;
        }
        if (appointment.BeginTime > appointment.EndTime)
        {
            ShowWarningMessage(GetLocalResourceObject("Msg12").ToString());     // 시작 시각이 종료 시각 보다 앞서야 합니다.
            return false;
        }

        if (AllDayCheckBox.Checked)
        {
            // 하루 종일이 선택된 경우
            appointment.Type |= Appointment.AppointmentType.AllDay;
            beginTime = new DateTime(beginTime.Year, beginTime.Month, beginTime.Day);
            if (endTime.Hour == 0 && endTime.Minute == 0)
                endTime = new DateTime(endTime.Year, endTime.Month, endTime.Day);
            else
                endTime = new DateTime(endTime.Year, endTime.Month, endTime.Day).AddDays(1);
            if (beginTime >= endTime) endTime = beginTime.AddDays(1);
            appointment.BeginTime = beginTime;
            appointment.EndTime = endTime;
        }
        else
        {
            appointment.BeginTime = beginTime;
            appointment.EndTime = endTime;
        }
        if (AlertCheckBox.Checked)
        {
            appointment.Type |= Appointment.AppointmentType.Alert;
        }
        if (AlertedCheckBox.Checked)
        {
            appointment.Type |= Appointment.AppointmentType.Alerted;
        }

        appointment.AlertMinute = int.Parse(AlertMinList.SelectedValue);
        appointment.Subject = SubjectTextBox.Value;
        appointment.Place = PlaceTextBox.Value;
        appointment.OrganizerName = WebUser.CurrentUser.Name;
        appointment.OrganizerEmail = WebUser.CurrentUser.MailAddress;
        byte[] bytes = new byte[32];
        Guid.NewGuid().ToByteArray().CopyTo(bytes, 0);
        string hex = BitConverter.ToString(bytes);
        appointment.UID = hex.Replace("-", "");
        appointment.BusyStatus = (Appointment.BusyStatusType)int.Parse(BusyStatusList.SelectedValue);
        appointment.Memo = WebUtil.GetHtmlWithContainer(HttpUtility.HtmlDecode(MemoTextBox.Value));
        // 참석자 처리
        foreach (string item in Attendees.Value.Split(new char[] { ';' }))
        {
            if (item.Length > 0)
            {
                List<RcptItem> rcptItems = NewMsgUtil.GetRecipientByType(item, NewMsgUtil.MsgType.To, NewMsgUtil.MsgSource.Email);
                RcptItem rcptItem = rcptItems[0];
                if (rcptItem.Value != "")
                {
                    if (rcptItem.Name == "") rcptItem.Name = rcptItem.Value.Split('@')[0];
                    appointment.Attendees.Add(new Attendee(rcptItem.Value, rcptItem.Name, Attendee.AttendeeType.Optional, Attendee.AttendeeStatus.ResponseUnknown));
                }
            }
        }
        // 참석자에 자신의 계정이 존재할 경우 Remove
        Attendee attendee = appointment.Attendees.Find(WebUser.CurrentUser.MailAddress);
        if (attendee != null) appointment.Attendees.Remove(attendee);

        switch (RecurList.SelectedValue)
        {
            case "1":
                {
                    appointment.RecurType = RecurrentAppointment.RecurrentType.EveryDay;
                    appointment.Recurrence.Interval = int.Parse(EverydayIntervalList.SelectedValue);
                }
                break;
            case "2":
                {
                    appointment.RecurType = RecurrentAppointment.RecurrentType.EveryWeek;
                    int dayOfWeek = 0;
                    if (WeekdayCheckBoxList1.Checked) dayOfWeek += int.Parse(WeekdayCheckBoxList1.Value);
                    if (WeekdayCheckBoxList2.Checked) dayOfWeek += int.Parse(WeekdayCheckBoxList2.Value);
                    if (WeekdayCheckBoxList3.Checked) dayOfWeek += int.Parse(WeekdayCheckBoxList3.Value);
                    if (WeekdayCheckBoxList4.Checked) dayOfWeek += int.Parse(WeekdayCheckBoxList4.Value);
                    if (WeekdayCheckBoxList5.Checked) dayOfWeek += int.Parse(WeekdayCheckBoxList5.Value);
                    if (WeekdayCheckBoxList6.Checked) dayOfWeek += int.Parse(WeekdayCheckBoxList6.Value);
                    if (WeekdayCheckBoxList7.Checked) dayOfWeek += int.Parse(WeekdayCheckBoxList7.Value);                    
                    appointment.Recurrence.Interval = int.Parse(EveryweekList.SelectedValue);
                    appointment.Recurrence.DayOfWeek = dayOfWeek;
                }
                break;
            case "3":
                {
                    if (EverymonthButton1.Checked)
                    {
                        appointment.RecurType = RecurrentAppointment.RecurrentType.EveryMonth;
                        appointment.Recurrence.Interval = int.Parse(EverymonthIntervalList.SelectedValue);
                        appointment.Recurrence.DayOfMonth = beginTime.Day;
                    }
                    else
                    {
                        appointment.RecurType = RecurrentAppointment.RecurrentType.EveryMonthDay;
                        appointment.Recurrence.Interval = int.Parse(MonthEveryList.SelectedValue);
                        appointment.Recurrence.WeekOfMonth = int.Parse(MonthOrderList.SelectedValue);
                        appointment.Recurrence.DayOfWeek = int.Parse(MonthOrderWeekList.SelectedValue);
                    }
                }
                break;
            case "4":
                {
                    if (EveryyearButton1.Checked)
                    {
                        appointment.RecurType = RecurrentAppointment.RecurrentType.EveryYear;
                        appointment.Recurrence.Interval = int.Parse(EveryyearIntervalList.SelectedValue);
                        appointment.Recurrence.MonthOfYear = beginTime.Month;
                        appointment.Recurrence.DayOfMonth = beginTime.Day;
                    }
                    else
                    {
                        appointment.RecurType = RecurrentAppointment.RecurrentType.EveryYearDay;
                        appointment.Recurrence.Interval = int.Parse(EveryyearIntervalList2.SelectedValue);
                        appointment.Recurrence.MonthOfYear = int.Parse(EveryyearMonthList.SelectedValue);
                        appointment.Recurrence.WeekOfMonth = int.Parse(EveryyearOrderList.SelectedValue);
                        appointment.Recurrence.DayOfWeek = int.Parse(EveryyearWeekList.SelectedValue);
                    }
                }
                break;
        }
        if (FinishButton1.Checked) appointment.RecurrentFinish.Type = RecurrentFinish.FinishType.None;
        else if (FinishButton2.Checked) appointment.RecurrentFinish.Type = RecurrentFinish.FinishType.Occurrence;
        else appointment.RecurrentFinish.Type = RecurrentFinish.FinishType.Until;
        appointment.RecurrentFinish.Occurrence = int.Parse(FinishRecurCountTextBox.Value);

        if (DateTime.TryParse(Request["FinishDate"], out date))
            appointment.RecurrentFinish.Until = date.AddSeconds(24 * 60 * 60 - 1);
        else
            appointment.RecurrentFinish.Until = _loginUser.GetLocalToday().AddSeconds(24 * 60 * 60 - 1);
        return true;
    }

    #endregion

    #region Updating Appointment

    private void UpdateAppointment()
    {
        // 쓰기 권한 검사
        McCalendar.RsAccessFlag accessFlag = McCalendar.GetAccessFlag(WebUser.CurrentUser.DomainUserID, _calId);
        if ((accessFlag & (McCalendar.RsAccessFlag.Write | McCalendar.RsAccessFlag.Admin)) == 0)
        {
            Response.Redirect("~/Error.aspx?code=0", true);
            return;
        }

        if (!_recur)
        {
            if (_appId != Guid.Empty)
            {
                // 일반 약속
                Appointment appointment = new Appointment(_appId);
                appointment.Load();
                Appointment newAppointment = new Appointment(_appId);
                newAppointment.Load();

                if (!GetAppointmentFromUI(newAppointment)) return;
                newAppointment.UID = appointment.UID;       // GetAppointmentFromUI()에서 새 UID가 할당되므로  원 UID로 돌린다.
                bool isEqual = IsEqualAppointment(appointment, newAppointment);
                newAppointment.Update();
                WebOperationLog.Write(WebUser.CurrentUser.MailAddress, Request.UserHostAddress, "M/Calendar/Edit.aspx", "ModifyApp", string.Format("CID:{0} AID:{1} S:{2}", _calId.ToString(), _appId.ToString(), appointment.Subject));
                ShowSuccessMessage(GetLocalResourceObject("Msg13").ToString());       // 약속이 올바르게 수정되었습니다.

                // 참석자가 존재하는 경우 메일을 발송한다.
                if (!isEqual && newAppointment.IsOriginMeetingRequest)
                {
                    newAppointment.MeetingStatus = Appointment.MeetingStatusType.IsMeeting;

                    MeetingRequest meetReq = new MeetingRequest(WebUser.CurrentUser.DomainUserID, WebUser.CurrentUser.Name, WebUser.CurrentUser.MailAddress);
                    meetReq.SendRequestMail(newAppointment);
                }
            }
            else
            {
                // 되풀이 예외
                Appointment appointment = new Appointment();
                if (!GetAppointmentFromUI(appointment)) return;
                // 되풀이 예외를 생성하기 위해서는 RecurrenceID와 ExceptionStartTime을 반드시 지정해야 한다.
                appointment.RecurrenceID = _recurId;
                DateTime exceptTime;
                if (DateTime.TryParse(WebParam.GetStrParamValue("begin"), out exceptTime))
                {
                    appointment.ExceptionStartTime = exceptTime;
                    McCalendar calendar = new McCalendar(_calId);
                    // 되풀이 예외 추가시 되풀이 약속에 대한 change 이벤트가 발생하지 않으므로 명시적으로 change 이벤트 발생이 필요
                    calendar.AddAppointment(appointment);
                    WebOperationLog.Write(WebUser.CurrentUser.MailAddress, Request.UserHostAddress, "M/Calendar/Edit.aspx", "AddRecurExcept", string.Format("CID:{0} AID:{1} S:{2}", _calId.ToString(), _appId.ToString(), appointment.Subject));
                    calendar.FireRecurrenceChangeEvent(_recurId);
                    ShowSuccessMessage(GetLocalResourceObject("Msg14").ToString());     // 되풀이 예외 약속이 올바르게 추가되었습니다.

                    if (appointment.IsOriginMeetingRequest)
                    {
                        appointment.MeetingStatus = Appointment.MeetingStatusType.IsMeeting;

                        MeetingRequest meetReq = new MeetingRequest(WebUser.CurrentUser.DomainUserID, WebUser.CurrentUser.Name, WebUser.CurrentUser.MailAddress);
                        meetReq.SendRequestMail(appointment);
                    }
                }
                else
                {
                    ShowWarningMessage(GetLocalResourceObject("Msg15").ToString());       // 변경된 약속 정보가 없습니다.
                }
            }
        }
        else
        {
            // 되풀이 약속
            RecurrentAppointment appointment = new RecurrentAppointment(_recurId);
            appointment.Load();
            RecurrentAppointment newAppointment = new RecurrentAppointment(_recurId);
            newAppointment.Load();

            if (!GetRecurrentAppointmentFromUI(newAppointment)) return;
            newAppointment.UID = appointment.UID;       // GetAppointmentFromUI()에서 새 UID가 할당되므로  원 UID로 돌린다.
            bool isEqual = IsEqualAppointment(appointment, newAppointment);

            string errMsg;
            if (newAppointment.ValidRecurrence(out errMsg))
            {
                newAppointment.Update();
                WebOperationLog.Write(WebUser.CurrentUser.MailAddress, Request.UserHostAddress, "M/Calendar/Edit.aspx", "ModifyRecur", string.Format("CID:{0}, AID:{1}, S:{2}", _calId.ToString(), _recurId.ToString(), appointment.Subject));
                ShowSuccessMessage(GetLocalResourceObject("Msg16").ToString());     // 되풀이 약속이 올바르게 수정되었습니다.

                if (!isEqual && newAppointment.IsOriginMeetingRequest)
                {
                    newAppointment.MeetingStatus = Appointment.MeetingStatusType.IsMeeting;

                    MeetingRequest meetReq = new MeetingRequest(WebUser.CurrentUser.DomainUserID, WebUser.CurrentUser.Name, WebUser.CurrentUser.MailAddress);
                    meetReq.SendRequestMail(newAppointment);
                }
            }
            else
            {
                ShowWarningMessage(errMsg);
            }
        }
    }

    private bool IsEqualAppointment(Appointment appointment, Appointment newAppointment)
    {
        if (appointment.Subject != newAppointment.Subject) return false;
        if (appointment.Place != newAppointment.Place) return false;
        if (appointment.BeginTime != newAppointment.BeginTime) return false;
        if (appointment.EndTime != newAppointment.EndTime) return false;
        if (appointment.Attendees.Count != newAppointment.Attendees.Count) return false;
        if (appointment.Memo != newAppointment.Memo) return false;
        return true;
    }

    private bool IsEqualAppointment(RecurrentAppointment appointment, RecurrentAppointment newAppointment)
    {
        if (appointment.Subject != newAppointment.Subject) return false;
        if (appointment.Place != newAppointment.Place) return false;
        if (appointment.BeginTime != newAppointment.BeginTime) return false;
        if (appointment.EndTime != newAppointment.EndTime) return false;
        if (appointment.Attendees.Count != newAppointment.Attendees.Count) return false;
        if (appointment.Memo != newAppointment.Memo) return false;
        if (!appointment.IsEqualRecurrenceRule(newAppointment)) return false;
        return true;
    }

    #endregion

    private void ShowWarningMessage(string msg)
    {
        MsgBox.Visible = true;
        MsgBox.CssClass = "alert alert-danger";
        MsgBoxLabel.Text = msg;
    }

    private void ShowSuccessMessage(string msg)
    {
        MsgBox.Visible = true;
        MsgBox.CssClass = "alert alert-success";
        MsgBoxLabel.Text = msg;
        string script = string.Format("GotoCalendarLater('{0}', '{1}');", _calId, _sdate);
        if (!ClientScript.IsClientScriptBlockRegistered(this.GetType(), "successMsgScript"))
            ClientScript.RegisterClientScriptBlock(this.GetType(), "successMsgScript", script, true);
    }

    protected string GetAttendeeStatusString(Attendee.AttendeeStatus status)
    {
        string retval = "";
        switch (status)
        {
            case Attendee.AttendeeStatus.ResponseUnknown: retval = Resources.Calendar.AttendeeStatus1; break;
            case Attendee.AttendeeStatus.Tentative: retval = Resources.Calendar.AttendeeStatus2; break;
            case Attendee.AttendeeStatus.Accept: retval = Resources.Calendar.AttendeeStatus3; break;
            case Attendee.AttendeeStatus.Decline: retval = Resources.Calendar.AttendeeStatus4; break;
        }
        return retval;
    }
}