/*
 * Assorted javascript functions used on Calendars.
 */

/* Hover over one thing shows the other with a timeout by adding the hoverClass specified */
function Hover(sourceId, targetId, hoverClass, timeout) {
  this.$source = jQuery('#' + sourceId);
  this.$target = jQuery('#' + targetId);
  this.hoverClass = hoverClass;
  this.isVisible = false;
  this.closeTimer = null;

  const _this = this;
  this.$source.on('hover', function() {
	  _this.open();
	  clearTimeout(_this.closeTimer);
  }, function(){
	  _this.closeTimer = setTimeout(function() {
		  _this.close();
	  }, timeout);
  });
}

//Instance methods
Hover.prototype = {
  open : function() {
    this.$target.addClass(this.hoverClass);
    this.isVisible = true;
  },

  close : function() {
    this.$target.removeClass(this.hoverClass);
    this.isVisible = false;
  }
};

function setAllTags(checked) {
  const checkBoxes = document.getElementById('tagList').getElementsByTagName('input');
  for (let i = 0;  i <checkBoxes.length; i++) {
    const box = checkBoxes[i];
    if (checked) {
      box.checked = true;
      jQuery(box.parentNode).addClass('checkedTag');
    } else {
	  box.checked = false;
	  jQuery(box.parentNode).removeClass('checkedTag');
    }
  }
}

/**
 * Reposition an element below a source element without going outside the current viewport.
 */
function reposition(sourceId,targetId) {
  	const $target = jQuery('#' + targetId);
  	const $parent = jQuery('#' + sourceId);
  	const $container = jQuery('#container, .id7-main-content'); // ignore the window, the element should always be inside container
  	const bestPosition = {
  			top : $parent.offset().top + $parent.height(),
  			left : $parent.offset().left
  	}

  	// shift left if necessary
	const maxY = $container.offset().left + $container.width() - 32; // bit of tolerance
	if (bestPosition.left + $target.width() > maxY) {
		bestPosition.left = maxY - $target.width();
	}

	// shift up if necessary
	const maxX = $container.offset().top + $container.height() - 32; // bit of tolerance
	if (bestPosition.top + $target.height() > maxX) {
		bestPosition.top = maxX - $target.height();
	}

	// jQuery can only correctly position a displayed element
	$target.css({ visibility: 'hidden' }).show().offset(bestPosition).css({ visibility: 'visible' });
}

const Checkbox = function(sourceCheckbox) {
  const name = sourceCheckbox.name;
  const id = sourceCheckbox.id;
  const span = document.createElement('span');
  const hidden = document.createElement('input');

  hidden.setAttribute('type','hidden');
  hidden.setAttribute('name', name);
  hidden.setAttribute('id', id);

  const image = document.createElement('img');
  image.src = Checkbox.shim;

  span.appendChild(hidden);
  span.appendChild(image);

  sourceCheckbox.parentNode.replaceChild(sourceCheckbox, span);
};
Checkbox.shim = '/static_war/images/shim.gif';

const DateFormat = {
  d_names : ["Sun", "Mon", "Tue",
    "Wed", "Thu", "Fri", "Sat"],
  m_names : ["Jan", "Feb", "Mar",
    "Apr", "May", "Jun", "Jul", "Aug", "Sep",
    "Oct", "Nov", "Dec"],
  padNumber : function(number) {
    let n = '' + number;
    while (n.length < 2) {  n = "0" + n; }
    return n;
  },
  dayName: function(dayNum) { return DateFormat.d_names[dayNum]; },
  monthName: function(monthNum) { return DateFormat.m_names[monthNum]; },

  toDateTime: function(dateObj, pattern) {
      let result = DateFormat.toShortDate();
      if (showTime) {
        result += ' ' + DateFormat.toTime();
      }
      return result;
  },
  toShortDate: function(dateObj) {
    let result = DateFormat.dayName(dateObj.getDay())+' '+dateObj.getDate()+' ' + DateFormat.monthName(dateObj.getMonth());
    if (dateObj.getFullYear() !== new Date().getFullYear) {
      result +=  ' ' + dateObj.getFullYear();
    }
    return result;
  },
  toTime: function(dateObj) {
    return DateFormat.padNumber(dateObj.getHours()) + ':' + DateFormat.padNumber(dateObj.getMinutes());
  }
};

function pluralise(count,singular,plural) {
  if (count === 1) return singular;
  if (count === 2) return 'other ' + singular;
  return count + ' ' + plural;
}

function toGMT(date, serverTimeOffset) {
  // eslint-disable-next-line no-param-reassign
  serverTimeOffset = serverTimeOffset || 0;
  return new Date(date.getTime() + (date.getTimezoneOffset() * 60000) + (serverTimeOffset * 60000))
}

const QuickAdd = {
  request : null,
  categories : [],
  onUpdate : function(e) {
    QuickAdd.updatePreview();
  },
  submitUrl : null,
  previewUrl : null,
  pageUrl : null,
  formSubmit : function() {
    const defaultUrl = QuickAdd.submitUrl;
    const value = jQuery.trim(jQuery('#quickAddQuery'));
    if (value.length === 0) {
      window.location = defaultUrl;
      return false;
    } else {
      return true; //continue with form submission.
    }
  },

  updatePreview : function() {
    const value = QuickAdd.getQuickAddValue();
    if (QuickAdd.request) {
       QuickAdd.request.abort();
    }

    if (value.length === 0) {
      jQuery('#quickAddPreview').hide();
      return;
    }

    let url = QuickAdd.previewUrl;

    QuickAdd.request = jQuery.ajax(url, {
    	type : 'POST',
    	data : 'sbrPage=' + QuickAdd.pageUrl + '&query=' + encodeURIComponent(value),
    	success : function(data) {
            const $quickAddPreview = jQuery('#quickAddPreview');
    		let resultsOkay = true;
    		$quickAddPreview.html('Error reading response');
    		let result = '';
    		for (let i=0; i<data.length; i++) {
    			const r = data[i];

    			let hasErrors = false;
    			for (let e in r.errors) {
    				hasErrors = true;
    				break;
    			}

    			if (!r.valid || hasErrors) {
    				resultsOkay = false;
    				result += '<div class="invalid">This doesn\'t look right; please rephrase.';
    				for (let code in r.errors) {
    					let message = r.errors[code];
    					result += '<div class="error">'+message+'</div>';
    				}
    				result += '</div>'
    			} else {
    				let item = r.item;
    				let timeResult = '';
    				if (item.allDay) timeResult += 'All day ';

    				// [SBTWO-2984] because DateTime is magical, we no longer need to do silly stuff like this
    				//                itemstart = toGMT(new Date(item.start),r.serverTimeOffset);
    				//                itemend = toGMT(new Date(item.end),r.serverTimeOffset);
    				const itemstart = new Date(item.start);
    				const itemend = new Date(item.end);

    				const startDate = DateFormat.toShortDate(itemstart);
    				timeResult += startDate;

    				if (!item.allDay) {
    					timeResult += ' ' + DateFormat.toTime(itemstart);
    				}

    				if (item.end > 1000*60*60*24*365) {
    					const endDate = DateFormat.toShortDate(itemend);
    					if (endDate !== startDate || !item.allDay) {
    						timeResult += ' - ';
    						if (endDate !== startDate) {
    							timeResult += endDate;
    						}
    						if (!item.allDay) {
    							timeResult += ' ' + DateFormat.toTime(itemend);
    						}
    					}
    				}

    				result += '<span class="title"><span class="attribute">What</span>&nbsp;' + item.title + '</span>';
    				result += '<span class="time"><span class="attribute">When</span>&nbsp;'+timeResult+'</span>';
    				result += '<span class="location"><span class="attribute">Where</span>&nbsp;' + item.location + '</span>';

    				let recurs = '';
    				let until = '?';
    				if (item.repeats !== 'never') {
    					until = DateFormat.toShortDate(new Date(item.until));
    				}

    				if (item.repeats === 'daily') {
    					recurs += 'Every ' + pluralise(item.interval,'day','days') + ' until ' + until;
    				} else if (item.repeats === 'weekly') {
    					const interval = (item.interval>1)?' every '+item.interval+' weeks' : '';
    					recurs += 'Every ';
    					if (item.monday) recurs += 'Monday, ';
    					if (item.tuesday) recurs += 'Tuesday, ';
    					if (item.wednesday) recurs += 'Wednesday, ';
    					if (item.thursday) recurs += 'Thursday, ';
    					if (item.friday) recurs += 'Friday, ';
    					if (item.saturday) recurs += 'Saturday, ';
    					if (item.sunday) recurs += 'Sunday ';
    					recurs += interval+' until ' + until;
    				} else if (item.repeats === 'everyWeekday') {
    					const interval = (item.interval>1)?' every ' + item.interval + ' weeks' : '';
    					recurs += 'Every weekday'+interval+' until ' + until;
    				} else if (item.repeats === 'monthly') {
    					recurs += 'Every ' + pluralise(item.interval,'month','months') + ' until ' + until;
    				} else if (item.repeats === 'yearly') {
    					recurs += 'Every ' + pluralise(item.interval,'year','years') + ' until ' + until;
    				}

    				result += '<span class="recurrence"><span class="attribute">Repeat</span>&nbsp;' + recurs + '</span>';

    				let tags = '';
    				for (let k = 0; k < item.categories.length; k++) {
    					tags += item.categories[k].name + ' ';
    				}
    				result += '<span class="tags"><span class="attribute">Tags</span>&nbsp;'+tags+'</span>';
    			}

    			let classname = 'event ';
    			for (let  k = 0; k < item.categories.length; k++) {
    				classname += ' ' + item.categories[k].cssClass;
    			}
    			$quickAddPreview.get(0).className = classname;
    		}
    		$quickAddPreview.html(result);
    		$quickAddPreview.show();
    	}
    });

  }
};

function shareButtonHTML(url, title) {
    const itemUrl = encodeURIComponent(url);
    const itemTitle = encodeURIComponent(title);
    return `
    <div class="dropup shareButtons">
        <a href="#" class="btn btn-default btn-sm dropdown-toggle" type="button" data-toggle="dropdown">
            <i class="fas fa-share-alt" aria-hidden="true" title="Share this"></i>
            <span class="sr-only">Share this</span>
        </a>
        <ul class="dropdown-menu">
            <li><a href="https://www.facebook.com/share.php?u=${itemUrl}" target="_blank">
                    <i class="fab fa-facebook-square fa-fw" aria-hidden="true" title="Share on Facebook"></i>
                    <span class="sr-only">Share on Facebook</span>
                </a></li>
            <li><a href="http://www.twitter.com/share?text=${itemTitle}&url=${itemUrl}" target="_blank">
                    <i class="fab fa-twitter-square fa-fw" aria-hidden="true" title="Share on X"></i>
                    <span class="sr-only">Share on X</span>
                </a></li>
            <li><a href="https://www.linkedin.com/sharing/share-offsite/?url=${itemUrl}" target="_blank">
                    <i class="fab fa-linkedin fa-fw" aria-hidden="true" title="Share on LinkedIn"></i>
                    <span class="sr-only">Share on LinkedIn</span>
                </a></li>
            <li><a href="mailto:?subject=${itemTitle}&body=${itemUrl}">
                    <i class="fas fa-envelope-square fa-fw" aria-hidden="true" title="Share via email"></i>
                    <span class="sr-only">Share via email</span>
                </a></li>
        </ul>
    </div>
    `;
}

jQuery(document).ready(function($) {
  $('.triggerPopover').on('click', function (e) {
    e.preventDefault();
    const el = jQuery(this);
    this.hide = jQuery.noop;

    const eventTitle = el.data('title');
    const event = el.data('event');
    const occurrence = el.data('occurrence');
    const location = el.data('location');
    const notes = el.data('notes');
    const detail = el.data('detail');
    const categories = el.data('categories').split(',');
    const moreInfo = el.data('more');
    const editingHost = el.data('editinghost');
    const sourceUrl = el.data('sourceurl');
    const sourceName = el.data('sourcename');
    const urlPath = el.data('urlpath');
    const showShareButtons = el.data('show-share-buttons');
    const pagePubliclyViewable = el.data('page-publicly-viewable');

    $('.triggerPopover').not(el).popover('hide');  // Hide other open popovers

    el.popover({
      placement: 'bottom',
      title: function() {
        let title = '<div class="eventActions">' +
          '<div class="eventPopoverName"><a href="' + sourceUrl + '?calendarItem=' + event + '" title="Link to event \'' + eventTitle + '\'">' + eventTitle + '</a></div>';

        if(el.data('canedit')) {
          title += '<div class="form-inline"><div class="btn-group form-group">' +
            '<a href="' + editingHost + '/sitebuilder2/edit/calendaritems/edit.htm?page=' + urlPath + '&amp;calendarItem=' + event + '" ' +
            'title="Edit \'' + eventTitle + '\'" class="btn btn-default btn-sm">' +
            '<i class="fa fa-fw fa-pencil-square-o"></i>' +
            '</a>' +
            '<a title="Delete \'' + eventTitle + '\'" aria-controls="calendarModal" ' +
              'data-action="delete" data-page="' + urlPath + '" data-event="' + event + '" data-occurrence="' + occurrence + '" class="btn btn-default btn-sm">' +
            '<i class="fa fa-fw fa-trash-o"></i>' +
            '</a>' +
            '<a href="' + editingHost + '/sitebuilder2/edit/calendaritems/create.htm?page=' + urlPath + '&amp;copyFrom=' + event + '" ' +
            'title="Copy \'' + eventTitle + '\'" class="btn btn-default btn-sm">' +
            '<i class="fa fa-fw fa-clone"></i>' +
            '</a>';

          if(el.data('recurring')) {
            title += '<a title="Unlink \'' + eventTitle + '\'" aria-controls="calendarModal" ' +
              'data-action="unlink" data-page="' + urlPath + '" data-event="' + event + '" class="btn btn-default btn-sm">' +
              '<i class="fa fa-fw fa-chain-broken"></i>' +
              '</a>';
          }
        }

        title += '<a href="' + editingHost + '/sitebuilder2/api/sitebuilder.ics?page=' + sourceUrl + '&amp;event=' + event + '" ' +
          'title="Export event \'' + eventTitle + '\'as iCalendar" class="btn btn-default btn-sm">' +
          '<i class="far fa-fw fa-calendar-star"></i>' +
          '</a>' +
          '</div></div></div>';

        return title;
      },
      content: function () {
        let content = '<p><strong>When: </strong><br />' + el.find('.time').html() + '</p>';

        if (location) {
          content += '<p><strong>Where:</strong><br />' + location + '</p>';
        }

        if (notes) {
          content += '<strong>Notes: </strong><br />' + notes;
        }

        if (detail) {
          content += '<strong>Detail: </strong><br />' + detail;
        }

        if (showShareButtons && pagePubliclyViewable) {
            content += shareButtonHTML(sourceUrl + '?calendarItem=' + event, eventTitle)
        }

        if (categories) {
          content += "<div class='tagsOnThisItem'>";
          const categoriesCSS = el.data('categoriescss').split(',');

            for(let i = 0; i < categories.length - 1; i++ ) {
              content += '<span class="event category ' + categoriesCSS[i] + '">' + categories[i] + '</span> ';
            }
          content += "</div>"
        }

        if (sourceName) {
          content += '<p><strong>Source: </strong><br /><a href="' + sourceUrl + '">' + sourceName + '</a></p>';

        }

        if (moreInfo) {
          content += '<p><a href="' + moreInfo + '">More info&hellip;</a></p>';
        }

        return content;
      },
      html: true,
      template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><button type="button" class="close" aria-hidden="true">&#215;</button><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
    });

    el.popover('show');
  });

  const $calendar = $('.calendar');

  $calendar.on('shown.bs.popover', function(e) {
    const $po = $(e.target).popover().data('bs.popover').tip();
    $po.data('creator', $(e.target));
  });

  $calendar.on('hidden.bs.popover', function(e) {
    const $creator = $(e.target);
    if ($creator) {
      $creator.data("bs.popover").inState.click = false;
    }
  });

  $calendar.on('click', '.popover .close', function(e) {
    e.preventDefault();
    const $creator = $(e.target).parents('.popover').data('creator');
    if ($creator) {
      $creator.popover('hide');
    }
  });

  $('body').on('click', '[data-target="#calendarModal"], [aria-controls="calendarModal"]', function (e) {
    e.preventDefault();
    const el = jQuery(this);
    const $calendarModal = jQuery('#calendarModal');
    const modalContent = $calendarModal.find('.dialog-content');
    const modal = $calendarModal[0];
    if (!modal.hasAttribute('open')) {
      // Throws unhelpful errors if it's already open for some reason
      modal.showModal();
    }
    modalContent.html(
      '<div class="dialog-body"><span class="loading"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i><span class="sr-only">Loading</span></span></div>'
    );
    jQuery.get('/sitebuilder2/render/edit/calendaritems/' + el.data('action') + '.htm', {
      sbrPage: el.data('page'),
      calendarItem: el.data('event'),
      occurrenceId: el.data('occurrence'),
      rn: new Date().getTime(),
    }).done(function(data) {
      modalContent.html(data);
    });
  });

  $(".dayLink").on("focus", function (e) {
     $(e.target).parents(".sb-calendar-date, td").find(".createNewItem").addClass("createNewItemHover");
  });

  $(".createNewItem").on("focusout", function () {
      $(this).removeClass("createNewItemHover");
  })
});
