var autolinker = new Autolinker( {
    urls : {
        schemeMatches : true,
        wwwMatches    : true,
        tldMatches    : true
    },
    email       : true,
    phone       : true,
    mention     : false,
    hashtag     : false,

    stripPrefix : true,
    stripTrailingSlash : true,
    newWindow   : true,

    truncate : {
        length   : 0,
        location : 'end'
    },

    className : ''
} );

var eventList = []
var recurringEventList = []
var cancelledEvents = {}

function Event (start, event) {
    if (!(start instanceof Date)) {
        start = start.toJSDate()
    }
    this.start = start
    this.event = event
    this.end = new Date(this.start.getTime() + this.event.duration.toSeconds()*1000)
    this.summary = event.summary || 'No title'
    this.description = event.description
    this.location = event.location || false
	this.isRecurring = event.isRecurring()

    this.lasts_several_days = this.start.toDateString() !== this.end.toDateString()
}

Event.prototype.isCancelled = function () {
    if (cancelledEvents[this.event.uid] instanceof Array
        && cancelledEvents[this.event.uid].includes(this.start.getTime())) return true
    return false
}

Event.prototype.toHTML = function () {
	
	var div_cal = document.createElement('div')
	    
	
	if (this.isRecurring) {
		
		div_cal.setAttribute('class', 'cal_entry')
		
		var div_datetime = document.createElement('div')
		div_datetime.setAttribute('class', 'cal_datetime')
		
		var span_summary = document.createElement('span')
		span_summary.setAttribute('class', 'cal_summary')
		span_summary.appendChild(document.createTextNode(this.summary))
		
		div_datetime.appendChild(span_summary)
		div_cal.appendChild(div_datetime)
		
		var div_description = document.createElement('div')
		div_description.setAttribute('class', 'cal_descriptionbox')
		
		var span_description = document.createElement('div')
		span_description.setAttribute('class', 'cal_description')
		
		if (this.description !== null) {
			var span_description = document.createElement('span')
			span_description.setAttribute('class', 'cal_description')
			span_description.innerHTML = autolinker.link( this.description )
		}
		
		div_description.appendChild(span_description)
		
		
		var span_next = document.createElement('span')
		span_next.setAttribute('class', 'cal_description')
		span_next.appendChild(document.createTextNode("Das nächste Treffen findet am " 
			+  this.start.toLocaleDateString('de-DE', {year: 'numeric', month: '2-digit', day: '2-digit'})
			+  " um " + this.start.toLocaleTimeString('de-DE', {hour: '2-digit', minute:'2-digit'})
			+ " statt."
		))
		
		div_description.appendChild(span_next)
		
		div_cal.appendChild(div_description)
	
		
	} else {
		
		div_cal.setAttribute('class', 'cal_entry')

		var div_datetime = document.createElement('div')
		div_datetime.setAttribute('class', 'cal_datetime')

		var span_date = document.createElement('span')
		span_date.setAttribute('class', 'cal_date')
		span_date.appendChild(document.createTextNode(this.start.toLocaleDateString('de-DE', {year: 'numeric', month: '2-digit', day: '2-digit'})))
		div_datetime.appendChild(span_date)

		if (this.lasts_several_days) {
			var span_end_date = document.createElement('span')
			span_end_date.setAttribute('class', 'cal_date')
			span_end_date.appendChild(document.createTextNode(' - ' + this.end.toLocaleString('de-DE', {year: 'numeric', month: '2-digit', day: '2-digit'})))
			div_datetime.appendChild(span_end_date)
		} else {
			var span_day = document.createElement('span')
			span_day.setAttribute('class', 'cal_day')
			span_day.appendChild((document.createTextNode(this.start.toLocaleDateString('de-DE', {weekday: 'long'}))))
			div_datetime.appendChild(span_day)
		}

		var span_time = document.createElement('span')
		span_time.setAttribute('class', 'cal_time')
		span_time.appendChild(document.createTextNode(this.start.toLocaleTimeString('de-DE', {hour: '2-digit', minute:'2-digit'})))
		div_datetime.appendChild(span_time)

		var span_summary = document.createElement('span')
		span_summary.setAttribute('class', 'cal_summary')
		span_summary.appendChild(document.createTextNode(this.summary))

		var div_description = document.createElement('div')
		div_description.setAttribute('class', 'cal_descriptionbox')
		div_description.appendChild(span_summary)

		if (this.location !== false) {
			var span_location = document.createElement('span')
			span_location.setAttribute('class', 'cal_location')

			var span_location_icon = document.createElement('i')
			span_location_icon.setAttribute('class', 'fa fa-map-marker')
			span_location_icon.setAttribute('aria-hidden', 'true')

			span_location.appendChild(span_location_icon)

			if (/s(ibyllastra(ss|ß)e )9/i.test(this.location)) {
				var a_location_osm = document.createElement('a')
				a_location_osm.setAttribute('href', 'https://www.openstreetmap.org/search?query=' + encodeURI(this.location))
				a_location_osm.appendChild(document.createTextNode(this.location))
				span_location.appendChild(a_location_osm)
			} else {
				span_location.appendChild(document.createTextNode(this.location))
				span_location.innerHTML = autolinker.link( span_location.innerHTML )
			}

			div_description.appendChild(span_location)
		}

		div_cal.appendChild(div_datetime)
		div_cal.appendChild(div_description)

		if (this.description !== null) {

				var span_description = document.createElement('span')
				span_description.setAttribute('class', 'cal_description')

				span_description.innerHTML = autolinker.link( this.description )

				div_description.appendChild(span_description)
		}

		// if (this.event.component.getFirstPropertyValue("status") == "CANCELLED") {
			// div_cal.style.textDecoration = 'line-through'
		// }
	}
	
	return div_cal

}

function parseIcalData(data) {
    var timeRangeStart = new Date()
    var timeRangeStop = new Date()
    timeRangeStart.setHours(0, 0, 0)
    timeRangeStop.setMonth(timeRangeStop.getMonth() + 3)

    var jcalData = ICAL.parse(data)
    var vcalendar = new ICAL.Component(jcalData)
    var events = vcalendar.getAllSubcomponents('vevent')

    events.map(function (e) {
        var event = new ICAL.Event(e)
        if (event.component.getFirstPropertyValue("status") == "CANCELLED") {
            if (!(cancelledEvents[event.uid] instanceof Array)) {
                cancelledEvents[event.uid] = []
            }

            cancelledEvents[event.uid].push(event.startDate.toJSDate().getTime())
        } else if (event.isRecurring()) {
            var expand = event.iterator()
            var next
            var exList = []
            event.component.getAllProperties('exdate').map(function (ex) {
                exList.push(ex.getFirstValue().toJSDate().getTime())
            })

			// particularly crappy code, but it works 
            while ((next = expand.next()) && next.toJSDate() < timeRangeStop) {
                if (!exList.includes(next.toJSDate().getTime()) && timeRangeStart < next.toJSDate() && next.toJSDate() < timeRangeStop) {
                    recurringEventList.push(new Event(next, event))
					break
                }
            }
			
        } else if (eventInTimeRange(event, timeRangeStart, timeRangeStop)) {
            eventList.push(new Event(event.startDate, event))
        }
    })
}

function eventInTimeRange(event, start, stop) {
    if (start < event.startDate.toJSDate() && event.startDate.toJSDate() < stop
        || start < event.endDate.toJSDate() && event.endDate.toJSDate() < stop
        || event.startDate.toJSDate() < start && stop < event.endDate.toJSDate()) return true
    return false
}

function orderEvents() {
    eventList.sort(function (e1, e2) {
        return e1.start - e2.start
    })
}

function writeEvents() {
    var cal = document.getElementById('calendar')

    cal.textContent = ''

	// TODO: Wenn EventList leer, dann Event-Abschnitt ausblenden
    if (eventList.length > 0) {
        eventList.map(function (e) {
            cal.appendChild(e.toHTML())
        })
		
    } else {
	
		cal.style.display = "none";
		var hevents = document.getElementById('hevents')
		hevents.style.display = "none";
    }
	
	var calRecur = document.getElementById('calendar-recurring')
    calRecur.textContent = ''

    if (recurringEventList.length > 0) {
        recurringEventList.map(function (e) {
            calRecur.appendChild(e.toHTML())
        })
    } else {
        calRecur.textContent = 'No events found.'
    }
	
}

function xhrRequest(url, callback, fail) {
    var xhr = new XMLHttpRequest()

    xhr.onreadystatechange = function () {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            if (xhr.status === 200) {
                callback(xhr.responseText)
            } else {
                fail(xhr.status)
            }
        }
    }

    xhr.open('GET', url)
    xhr.send()
}

function processData(data) {
    parseIcalData(data)
    orderEvents()
    writeEvents()
}

function requestFailed(status) {
    document.getElementById('calendar').textContent = 'Something has gone wrong. Try reloading the page.'
	// document.getElementById('calendar-recurring').textContent = 'Something has gone wrong. Try reloading the page.'
}

xhrRequest('https://cloud.chaospott.de/remote.php/dav/public-calendars/5HM7B0ZOLEYC3QD0?export', processData, requestFailed)
