/*
    These are script elements used by the user-interface portion of the
    various plugin widgets.
*/
/*
Copyright 2013-2017, MH Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
/** 
  * the reference to cd_scriptvars is kind of weird. The 
  * wp_localize_script method defines cd_scriptvars as 
  * a page global object that contains the contents of the 
  * localization array. 
  *  
  * The RESPONSIVE_BREAK_SIZE is the size at which we're 
  * changing our behavior to be responsive.
  */
var CDaily= typeof(CDaily)== 'undefined' ?  {
    "ajaxURL" : cd_scriptvars.ajaxURL,
    "RESPONSIVE_BREAK_SIZE" : 600,
    "DEFAULT_DIALOG_WIDTH"  : 600
} : CDaily ;


/**
 * This function is called by the Detailed List when it's 
 * running in responsive mode. 
 */
CDaily['showSingleEvent']=function(htmlData) {
    CDaily.showDialog(htmlData);
};

/**
 * Display a dialog with event data that's stored locally in
 * JSON. This script is dependent upon jQuery and jQuery UI -
 * Dialog.
 *
 * @param targetID - Selector for element to receive data.
 * @param jsonData - Cached data of events.
 * @param offset - The offset into the array to get the data
 *  			 for.
 */
CDaily["showEventJSON"]=function(jsonData, offset) {
    CDaily.showDialog(jsonData.events[offset]);
};

/**
 * This is a wrapper method for displaying a dialog. It hides 
 * the CMS specific details of how to do it from the rest of the 
 * code. 
 */
CDaily["showDialog"]=function(content,title){
    jQuery(function() {
        if (CDaily.JOOMLA) {
            var myDialog='<div class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="mod_f_a" aria-hidden="true">';
            if (title!=null) {
                myDialog+='<div class="modal-header">'+title+'</div>';
            }
            myDialog+='<div class="modal-body CDDisplayAlways">'+content+'</div>'+
                '<div class="modal-footer">'+
                '<button class="btn" data-dismiss="modal" aria-hidden="true">'+CDaily.Captions["COM_CONNECTDAILY_Close"]+'</button>'+
                '</div>'+
                '</div>';
                           
            var element=jQuery(myDialog);

            if (typeof addthis != 'undefined') {
                /*
                    This is kind of funky, but if you call addthis before the event fires, it doesn't work.
                */
                jQuery(element).on('shown.bs.modal',function(){
                    addthis.toolbox('.addthis_inline_share_toolbox');
                    if (addthis.layers.refresh){
                        addthis.layers.refresh();
                    }
                });
            }
            /*
                Joomla includes the Twitter Bootstrap.modal() method. Use it.
            */
            element.modal('show');
        } else {
            var element=jQuery('<div class="CDDisplayAlways" style="padding: 0.5em;" />'),
                    params={
                    dialogClass: "wp-dialog",
                    height: jQuery(window).height() * 0.8,
                    width: jQuery(window).width() > CDaily.RESPONSIVE_BREAK_SIZE ? CDaily.DEFAULT_DIALOG_WIDTH : 0.9 * jQuery(window).width(),
                    modal: true,
                    zIndex: 10000   // the menu can cause problems so we need to be over it.
                };

            if (title!=null) {
                params['title']=title;
            }
            element.html(content);
            element.dialog(params);
            if (typeof addthis != 'undefined') {
                addthis.toolbox('.addthis_inline_share_toolbox');
                if (addthis.layers.refresh){
                	addthis.layers.refresh();
                }
            }
        }
    });
};

CDaily["leapYear"]=function(yr) {
    if (yr % 4 == 0) {
        if (yr % 400 == 0) {
            return 1;
        } else if (yr % 100 == 0) {
            return 0;
        } else {
            return 1;
        }
    }
    return 0;
};

CDaily["daysPerMonth"]=function(yr, month) {
    var iResult = 0;
    switch (month) {
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12:
        iResult = 31;
        break;
    case 2:
        iResult = 28 + CDaily.leapYear(yr);
        break;
    case 4:
    case 6:
    case 9:
    case 11 :
        iResult = 30;
        break;
    default:
        break;
    }
    return iResult;
};

/**
 * Render a month view calendar. This mimics the wordpress
 * wp_get_calendar() function so that appearance and style are
 * identical.
 *
 * @param yr, the year (4 digit integer)
 * @param month, the month 1-12
 * @param hotString - A string of 1's and 0's where a 1 indicates that day has
 *    events, and a 0 indicates it does not.
 *
 * localizationData looks like:
 *
 * data {
 *
 * MonthNames array 0..11 of string
 * AbbrMonthNames array 0..11 of string
 * DayNames array 0..6 of string
 * AbbrDayNames array 0..6 of string
 * DayInitials array 0..6 of String
 * FirstDayOfWeek integer - [0]-[6]
 * }
 */
CDaily["renderCalendar"]=function(yr, month, hotString) {
    
    var localizationData=CDaily.localizationData;
    var sResult = '', iDay = localizationData.FirstDayOfWeek;
    sResult += '<table class="cd-calendar" id="wp-calendar">';
    sResult += '<caption>' + localizationData.MonthNames[month - 1] + " " + yr + "</caption>";
    sResult += '<thead><tr>';

    for (var i = 0; i < 7; i++) {
        sResult += "<th scope=\"col\" title=\"" + localizationData.DayNames[iDay] + "\">" + localizationData.DayInitials[iDay] + "</th>";
        if (++iDay == 7) {
            iDay = 0;
        }
    }
    /*
        The IDs of prev and next are used by the wordpress calendar and we want to
        inherit their styling.
    */
    sResult += "</tr></thead><tbody>";

    var dt = new Date(yr, month - 1, 1),iDate = 1,iDaysPerMonth = CDaily.daysPerMonth(yr, month), 
        dToday=new Date(),
        iToday=dToday.getDate(), iThisMonth=dToday.getMonth(), iThisYear=dToday.getFullYear(),
        bFirst = true,
        bToday = false;
    iDay = dt.getDay();
    do {
        sResult += "<tr>";
        if (bFirst) {
            bFirst = false;
            if (iDay != localizationData.FirstDayOfWeek) {
                if (localizationData.FirstDayOfWeek == 0) {
                    sResult += "<td class=\"pad\" colspan=\"" + iDay + "\"> </td>";
                } else {
                    sResult += "<td class=\"pad\" colspan=\"" + (iDay == 0 ? 6 : iDay - localizationData.FirstDayOfWeek) + "\"> </td>";
                }
            }
        }
        do {
            bToday=(iDate==iToday && yr==iThisYear && (iThisMonth==(month-1)));
            sResult+="<td"+(bToday ? ' class="CDToday"' : '') +">";
            if (hotString.charAt(iDate - 1) == '0') {
                sResult += iDate + "</td>";
            } else {
                sResult += "<a data-year=\""+yr+"\" data-month=\""+month+"\" data-day=\""+iDate+"\""+
                    ( bToday ? " class=\"CDSelectedDay\"" : "")+
                    ">" + iDate + "</a></td>";
            }
            iDate++;
            if (++iDay > 6) {
                iDay = 0;
            }
        } while (iDate <= iDaysPerMonth && iDay != localizationData.FirstDayOfWeek);
        if (iDay != localizationData.FirstDayOfWeek) {
            // We're at month end. Pad it out.
            if (localizationData.FirstDayOfWeek == 0) {
                sResult += '<td class="pad" colspan="' + (7 - iDay) + '"> </td>'
            } else {
                sResult += '<td class="pad" colspan="' + (iDay == 0 ? 1 : 7 - iDay + localizationData.FirstDayOfWeek) + '"> </td>'
            }
        }
        sResult += "</tr>";
    } while (iDate <= iDaysPerMonth);
    sResult += "</tbody><tfoot><tr>" +
        "<td colspan=\"3\" id=\"prev\" data-year=\""+yr + "\" data-month=\"" + month + "\" data-direction=\"-1\" class=\"pad\">«</td>" +
        "<td class=\"pad\"> </td>" +
        "<td colspan=\"3\" id=\"next\" data-year=\""+yr + "\" data-month=\"" + month + "\" data-direction=\"1\" class=\"pad\">»</td>" +
        "</tr></tfoot></table>";
    return sResult;
};

CDaily["showEventsForDay"]=function(htmlData, theDate, targetDiv) {
    //  console.log("htmlData="+htmlData);
    /*
        Try to pick out the locale formatted date from
        the content stream.
    */
    var expr=new RegExp("^<h1 [^>]+>([^<]+)</h1>"),
        a=expr.exec(htmlData.trim());
    if (Array.isArray(a)) {
        theDate=a[1];
    }
    /*
        Show the dialog.
    */
    if (targetDiv==null || (typeof targetDiv == 'undefined')) {
        CDaily.showDialog(htmlData, theDate);
    } else {
        jQuery(targetDiv).html('<h2>'+theDate+'</h2>'+htmlData);
        if (typeof addthis != 'undefined') {
            addthis.toolbox('.addthis_inline_share_toolbox');
            if (addthis.layers.refresh){
                addthis.layers.refresh();
            }
        }
    }

    
};

CDaily["getJulianDayNumber"]=function(yr, mo, da) {
    var dt = new Date(yr, mo - 1, da);
    return Math.floor((dt.getTime() / 86400000) -
                      (dt.getTimezoneOffset() / 1440) + 2440588);

};


CDaily["stopEvent"]=function(event) {
    if (event != null && event.stopPropagation) {
        event.stopPropagation();
    }
};

/**
 * Add translation captions to the CDaily Global object.
 */
CDaily["addCaptions"]=function(newCaptions){

    if (!CDaily.hasOwnProperty("Captions")) {
        CDaily["Captions"]={};
    }
    var captions=CDaily.Captions;
    for (var i=0; i < newCaptions.captions.length; i++) {
        var thisCaption=newCaptions.captions[i];
        captions[thisCaption.caption]=thisCaption.value;
    }

}

/**
 * Test if this browser supports date fields in a real way.
 */
CDaily["browserSupportsDateFields"]=function(){
    /* 
       This works by instantiating a date input, setting
       the value to an invalid value, and then reading
       the value back out.
     
       If it's really a date value, the invalid value won't
       come back.
    */
    var b=document.createElement('input');
    try {
        b.type='date';
        b.value='banana';
    } catch (err) {
        // IE throws an error here. Catch it. 
        return false;
    }
    return b.value!='banana';
};

/**
 * Setup the various event hooks for the add events form.
 */
CDaily["setupAddEventsForm"]=function(){
    
    if (!CDaily.browserSupportsDateFields()) {
        /*
            The browser doesn't support date pickers, use a javascript one.
        */
        if (typeof jQuery.datepicker == 'object') {
            jQuery('#idCDstarting_date, #idCDending_date, #idCDrecurrence_start, #idCDrecurrence_end').datepicker({"dateFormat": "yy-mm-dd"});
        }
    }

    /*
        On Calendar Dropdown change, set event type to default.
    */
    var dd=document.getElementById('idCDcalendar_id');
    if (dd!=null) {
        jQuery(dd).on('change',function(event){
            var dd=event.target,
                type=jQuery(dd.options[dd.selectedIndex]).attr('data-default_type'),
                ddType=jQuery("#idCDitem_type_id option[value='"+type+"']");
            jQuery(ddType).attr('selected',true);
        });
    }


    /*
        Hook the recurrence type options to show/hide the
        various elements as required.
    */
    jQuery("[name='CDrec_type']").on('click',function(event) {
        var a=[
            '.CDOneTimeFields',
            '.CDAnnualOptions',
            '.CDRepeatOn',
            '.CDRepeatEveryOpt',
            '.CDRepeatEveryN',
            '.CDMonthlyOnly',
            '.CDDOWChecks',
            '.CDOrdinalChecks',
            '.CDDailyFields',
            '.CDWeeklyOnly',
            '.CDRecurring'
        ];

        var sClasses=jQuery(event.target).attr('data-require-classes');
        for (var i=0; i < a.length; i++) {
            jQuery(a[i]).each(function(index) {
                if (sClasses.indexOf(a[i])>=0) {
                    jQuery(this).fadeIn();
                } else {
                    jQuery(this).fadeOut();
                }
            });
        }

    });
    jQuery("input[name='CDrec_type']:checked").click();

    /*
        Hook the start date on-change to auto-populate the end date.
    */
    jQuery('#idCDstarting_date').on('change',function(){
        if (jQuery('#idCDending_date').val()=='') {
            jQuery('#idCDending_date').val(jQuery('#idCDstarting_date').val());
        }
    });

    /*
        Hook the Day of Month number to select the Day Radio
    */
    jQuery('#idCDday').on('change',function(element){
        jQuery('#idCDrgRecurDaily').prop('checked',true);
        });

    jQuery("input[name='CDrecur_array[]']").on('change',function(event){
        if (jQuery(event.target).prop('checked')) {
            jQuery('#idCDrgRecurEvery').prop('checked',true);
        }
    });
    /*
        Hook the Day of week and ordinal checkboxes to select the
        every radio.
    */
    jQuery("[name='CDday_array[]']").on('click',function(event){

        if (!jQuery(event.target).prop('checked')) {
            return;
        }

        var val=parseInt(jQuery(event.target).val());

        jQuery('#idCDrgRecurEvery').prop('checked',true);

        jQuery("[name='CDday_array[]']").each(function(index,element){
            var thisVal=parseInt(jQuery(element).val());
            if (val<8 && thisVal>=8) {
                /*
                    If a day of week is checked, uncheck day, weekday, and weekend day.
                */
                jQuery(element).removeProp('checked');
            } else if (val==8 && thisVal!=val) {
                jQuery(element).removeProp('checked')
            } else if (val>8 && thisVal<= 8) {
                jQuery(element).removeProp('checked');
            }
        });
    });
    /*
        Hooks for Locations
    */
    var loc=document.getElementById('idCDlocation_name');
    if (loc!=null) {
        // The input device can be a text box, or a select depending upon
        // whether the user has permission to add locations.
        if (typeof jQuery(loc).attr('list') == 'string') {
            // This is the text box tied to a list.
            jQuery(loc).on('change',function(event){
                /*
                    Here's what we need to do:
                 
                    find the current value in our option list.
                 
                    if we find the address
                 
                        put the address in the text box.
                 
                        If the address is verified, make the address read-only,
                        otherwise, remove the readonly attribute.
                 
                    else
                 
                        Enable the address text box
                */
                var lst=document.getElementById(jQuery(this).attr('list')),
                    curValue=this.value.trim(),
                    bFound=false;
                for (var i=0; i < lst.options.length; i++) {
                    var opt=lst.options[i];
                    if (curValue==opt.value) {
                        bFound=true;
                        document.frmCDAddEventForm.CDlocation_id.value=jQuery(opt).attr("data-location-id");
                        jQuery('#idCDlocation_address').val(jQuery(opt).attr('data-address'));
                        if ("1"==jQuery(opt).attr('data-verified')) {
                            jQuery('#idCDlocation_address').prop('readonly',true);
                        } else {
                            jQuery('#idCDlocation_address').removeProp('readonly');
                        }
                        break;
                    }
                }
                if (!bFound) {
                    document.frmCDAddEventForm.CDlocation_id.value='0';
                    jQuery('#idCDlocation_address').removeProp('readonly');
                }
             });
        } else {
            // This is a select
            jQuery(loc).on('change',function(event) {
                    var opt=this.options[this.selectedIndex];
                    document.frmCDAddEventForm.CDlocation_id.value=opt.value;
                    jQuery('#idCDlocation_address').val(jQuery(opt).attr('data-location_address'));
                });
        }
    }

    jQuery("input[name='CDrec_type']").on('change',function(event){
        var iValue=parseInt(jQuery(event.target).val());
        if ((iValue==0) || (iValue==5)) {
            jQuery('#idCDrgRecurEvery').prop('checked',true);
        }
    });

    /* Hook expansion of resources quantities. */
    jQuery(".ResourceCheckbox").click(function(){
            CDaily.unhideResourceQuantity(this);
        });

    /*
        If the Userland submit hook CDaily.userAddSubmitHook
        exists, hook it to the form on submit.
    */
    if (typeof CDaily['userAddSubmitHook'] == 'function') {
        jQuery('#idCDAddEventForm').on('submit',CDaily['userAddSubmitHook']);
    }
    /*
        If the Userland initHook CDaily.userAddInitHook exists,
        invoke it.
    */
    if (typeof CDaily['userAddInitHook'] == 'function') {
        CDaily.userAddInitHook();
    }
};

/**
 * onClick handler for the view events filter.
 */
CDaily["handleEventFilter"]=function(FilterDivID,element) {
    // alert(FilterDivID +" Value: "+element.value+" Checked: "+element.checked);
    var filterID=parseInt(element.value,10),
        bChecked=element.checked,
        allBox=jQuery('#'+FilterDivID+"_All")[0];

    if (filterID==-1) {
        // This is the Check All/Uncheck All checkbox. Set the child checkboxes to follow suit.
        jQuery('#'+FilterDivID+' input[type="checkbox"]').attr("checked",bChecked);
    } else {
        /*
            We're filtering for one specific filterID
        */
        if (bChecked) {
            /*
                Find out if ALL of the filter checkboxes are checked, and if so, set
                the value for the All checkbox.
            */
            var bAll=true;
            jQuery('#'+FilterDivID+' input[type="checkbox"]').each(function(index,ele) { 
                    if (ele.value!="-1") { 
                        bAll &= ele.checked 
                    }  
                });
            if (bAll) {
                allBox.checked=true;
            }
        } else {
            allBox.checked=false;
        }
    }
    jQuery('#'+FilterDivID+'_UncheckAll').css("display", allBox.checked ? "inline" : "none");
    jQuery('#'+FilterDivID+'_CheckAll').css("display", allBox.checked ? "none" : "inline");
    CDaily.applyFilter(FilterDivID);
};

/**
 * Apply the filter based on the current checkboxes. 
 *  
 *      Iterate over them and set the display value for the
 *      events in the calendar. If the item should be displayed,
 *      we set "display" to empty (the default). If it should
 *      be hidden, we set display to "none".
 *  
 *      @param FilterDivID The ID of the Container of the filter
 *                         checkboxes.
 */
CDaily["applyFilter"]=function(FilterDivID) {
    var allBox=jQuery('#'+FilterDivID+"_All")[0];
    if (allBox.checked) {
        jQuery(".CDEventTitle").css("display","");
        jQuery(".CDTimeLabel").css("display",""); 
    } else {
        var showLabels={}, hideLabels=[], anyChecked=false;
        jQuery('#'+FilterDivID+' input[type="checkbox"]').each(function(index,eleOuter) { 
            if (eleOuter.value!="-1") {
                var fld=CDaily[FilterDivID].filter_field,
                    expr='.CDEventTitle['+fld+'="'+eleOuter.value+'"]';
                jQuery(expr).each(function(index,ele){
                    anyChecked|=eleOuter.checked;
                    jQuery(ele).css("display",eleOuter.checked ? "" : "none");
                    var label=jQuery(ele).attr("data-time_label");
                    if ( (typeof label) != 'undefined' ) {
                        if (eleOuter.checked) {
                            showLabels[label]=true;
                            jQuery('#'+label).css("display","");
                        } else {
                            hideLabels.push(label);
                        }
                    }
                });
            }
        });
        if (!anyChecked) {
            jQuery(".CDEventTitle").css("display","none");
            jQuery(".CDTimeLabel").css("display","none"); 
        }
        for (var i = 0; i < hideLabels.length; i++) {
            /*
                Hide labels that are not shared with a displayed
                event.
            */
            if (!showLabels.hasOwnProperty(hideLabels[i])) {
                jQuery('#'+hideLabels[i]).css("display","none");
            }
        }
    }
}

CDaily['concatenateParameters']=function(sURL,sParameters){
    var result=sURL;
    if (sURL.indexOf('?')>0) {
        if (sParameters.indexOf("&")==0) {
            result+=sParameters;
        } else {
            result+="&"+sParameters;
        }
    } else {
        result+="?"+sParameters;
    }
    return result;
}

CDaily['eventClick'] = function(cal_item_id, date) {
    var sURL = CDaily.concatenateParameters(CDaily["ajaxURL"],(CDaily.JOOMLA ? "" : "action=cdaily&sub")+"action=cd_viewitem&format=raw&cal_item_id=" + cal_item_id + "&date=" + date);
    jQuery.ajax( {
        "dataType": "html",
        "timeout": 15000,
        "url": sURL,
        "success": function(data, textStatus, jqXHR) {
            CDaily.showSingleEvent(data);
        }
    }).error(function(jqxhr, status, error) {
            alert(error);
        });
}

/**
 * Iterate over the Resource selections and save the value onto 
 * the resource_list hidden input. The element is saved as the 
 * string representation of a JSON Object in array format. E.G. 
 *  
 * { "values" : [ ["1","2"],["3","33"]]} 
 *  
 * Column 0 of the inner array is the resource ID, and 
 * column 1 is the qty used. Default value is one. 
 *  
 * @return true Always 
 */
CDaily['saveResources'] = function(){
    var s='{ "values" : [ ',
        ele=document.getElementById('IDHresource_list');
    if (ele==null) {
        return true;
    }
    jQuery('.ResourceCheckbox').each(function(ix,node){
        if (node.checked) {
            s += '["' + node.value + '","';
            var qty=document.getElementById('IDCDresourceQuantity'+node.value);
                if (qty===null) {
                    s+='1';
                } else {
                    s+=qty.value;
                }
                s+='"],';
        }
    });
    s = s.substring(0,s.length-1)+' ]}';
    ele.value=s;
    return true;
}

/**
 * In response to clicking on a resource checkbox, hide or 
 * unhide the corresponding quantity box. 
 *  
 * @param node The checkbox element for the resource. 
 */
CDaily['unhideResourceQuantity'] = function(node){
    var selector='#IDlblCDResourceQuantity'+node.value;
    if (node.checked) {
        jQuery(selector).removeClass("Unselected");
    } else {
        jQuery(selector).addClass("Unselected");
    }
    return true;
}