
(function($) {
    var defaults = {
    	effect: "fx1"
    };

    $.fn.textHoverMaster = function(options) {
        var args = $.extend({}, defaults, options);

        return this.each(function() {
			var effs = {
				"fx1": {
					in: {
						duration: 1000,
						delay: (el, i) => 75+i*40,
						easing: 'easeOutElastic',
						elasticity: 650,
						opacity: {
							value: 1,
							easing: 'easeOutExpo',
						},
						translateY: ['50%','0%']
					},
					out: {
						duration: 400,
						delay: function(el, index) { return index*40; },
						easing: 'easeOutExpo',
						opacity: 0,
						translateY: '-100%'
					}
				},
				"fx2": {
					in: {
						duration: 700,
						easing: "easeOutCirc",
						opacity: 1,
						translateX: (el, i) => [(50 + i*10), 0],
						delay: (el, i) => i*50
					},
					out: {
						duration: 0,
						opacity: 0
					}
				},
				"fx3": {
					in: {
						duration: 800,
						easing: "easeOutElastic",
						opacity: 1,
						translateY: (el, i) => i%2 === 0 ? ["-80%", "0%"] : ["80%", "0%"],
						delay: (el, i) => i*50
					},
					out: {
						duration: 800,
						delay: function(el, index) { return index*50; },
						easing: 'easeOutExpo',
						opacity: 0,
						translateY: function(el, index) {
							return index%2 === 0 ? '80%' : '-80%';
						}
					}
				},
				"fx4": {
					in: {
						duration: 700,
						easing: "easeOutElastic",
						opacity: 1,
						translateY: (el, i) => i%2 === 0 ? ["-80%", "0%"] : ["80%", "0%"],
						rotateZ: [90,0],
						delay: (el, i) => (el.parentNode.parentNode.children.length-i-1)*80
					},
					out: {
						duration: 500,
						delay: function(el, index) { return (el.parentNode.children.length-index-1)*80; },
						easing: 'easeOutExpo',
						opacity: 0,
						translateY: function(el, index) {
							return index%2 === 0 ? '80%' : '-80%';
						},
						rotateZ: function(el, index) {
							return index%2 === 0 ? -25 : 25;
						}
					}
				},
				"fx5": {
					in: {
						duration: 700,
						delay: (el, i) => 550+i*50,
						easing: 'easeOutQuint',
						opacity: [0,1],
						translateY: ['-100%','0%'],
						rotateY: [180,0]
					},
					out: {
						duration: 700,
						delay: function(el, index) { return index*60; },
						easing: 'easeInQuint',
						opacity: {
							value: 0,
							easing: 'linear',
						},
						translateY: '150%',
						rotateY: -180
					}
				},
				"fx6": {
					in: {
						duration: 600,
						easing: 'easeOutQuart',
						opacity: 1,
						translateY: (el, i) => i%2 === 0 ? ['-40%', '0%'] : ['40%', '0%'],
						rotateZ: [10,0]
					},
					out: {
						duration: 0,
						opacity: 0
					}
				},
				"fx7": {
					in: {
						duration: 250,
						delay: (el, i) => 200+i*25,
						easing: 'easeOutCubic',
						opacity: 1,
						translateY: ['-50%','0%']
					},
					out: {
						duration: 250,
						delay: function(el, index) { return index*25; },
						easing: 'easeOutCubic',
						opacity: 0,
						translateY: '50%'
					}
				},
				"fx8": {
					in: {
						duration: 400,
						delay: (el, i) => 150+(el.parentNode.parentNode.children.length-i-1)*20,
						easing: 'easeOutQuad',
						opacity: 1,
						translateY: ['100%','0%']
					},
					out: {
						duration: 400,
						delay: function(el, index) { return (el.parentNode.children.length-index-1)*20; },
						easing: 'easeInOutQuad',
						opacity: 0,
						translateY: '-100%'
					}
				},
				"fx9": {
					in: {
						duration: 400,
						delay: (el, i) => i*50,
						easing: 'easeOutSine',
						opacity: 1,
						rotateY: [-90,0]
					},
					out: {
						duration: 200,
						delay: function(el, index) { return index*50; },
						easing: 'easeOutSine',
						opacity: 0,
						rotateY: 45
					}
				},
				"fx10": {
					in: {
						duration: 1000,
						delay: (el, i) => 100+i*30,
						easing: 'easeOutElastic',
						elasticity: anime.random(400, 700),
						opacity: 1,
						rotateZ: (el, i) => [anime.random(20,40),0]
					},
					out: {
						duration: 0,
						opacity: 0
					}
				},
				"fx11": {
					in: {
						duration: 400,
						delay: (el, i) => 200+i*20,
						easing: 'easeOutExpo',
						opacity: 1,
						rotateY: [-90,0]
					},
					out: {
						duration: 400,
						delay: function(el, index) { return index*20; },
						easing: 'easeOutExpo',
						opacity: 0,
						rotateY: 90
					}
				},
				"fx12": {
					in: {
						duration: 400,
						delay: (el, i) => 200+i*30,
						easing: 'easeOutExpo',
						opacity: 1,
						rotateX: [90,0]
					},
					out: {
						duration: 400,
						delay: function(el, index) { return index*30; },
						easing: 'easeOutExpo',
						opacity: 0,
						rotateX: -90
					}
				},
				"fx13": {
					in: {
						duration: 800,
						easing: 'easeOutExpo',
						opacity: 1,
						translateY: function(el, index) {
							var p = el.parentNode.parentNode,
								lastElOffW = p.lastElementChild.offsetWidth,
								firstElOffL = p.firstElementChild.offsetLeft,
								w = p.offsetWidth - lastElOffW - firstElOffL - (p.offsetWidth - lastElOffW - p.lastElementChild.offsetLeft),
								tyVal = lineEq(0, 200, firstElOffL + w/2, firstElOffL, el.offsetLeft);

							return [Math.abs(tyVal)+50+'%','0%'];
						},
						rotateZ: function(el, index) {
							var p = el.parentNode.parentNode,
								lastElOffW = p.lastElementChild.offsetWidth,
								firstElOffL = p.firstElementChild.offsetLeft,
								w = p.offsetWidth - lastElOffW - p.firstElementChild.offsetLeft - (p.offsetWidth - lastElOffW - p.lastElementChild.offsetLeft),
								rz = lineEq(90, -90,firstElOffL + w, firstElOffL, el.offsetLeft);

							return [rz,0];
						}
					},
					out: {
						duration: 500,
						easing: 'easeOutExpo',
						opacity: 0,
						translateY: '-150%'
					}
				},
				"fx14": {
					in: {
						duration: 500,
						easing: 'easeOutExpo',
						delay: function(el, index) { return 200+index*30; },
						opacity: 1,
						rotateZ: [20,0],
						translateY: function(el, index) {
							var p = el.parentNode.parentNode,
								lastElOffW = p.lastElementChild.offsetWidth,
								firstElOffL = p.firstElementChild.offsetLeft,
								w = p.offsetWidth - lastElOffW - firstElOffL - (p.offsetWidth - lastElOffW - p.lastElementChild.offsetLeft),
								tyVal = lineEq(-130, -60, firstElOffL+w, firstElOffL, el.offsetLeft);

							return [Math.abs(tyVal)+'%','0%'];
						}
					},
					out: {
						duration: 400,
						easing: 'easeOutExpo',
						delay: function(el, index) { return (el.parentNode.children.length-index-1)*30; },
						opacity: 0,
						rotateZ: 20,
						translateY: function(el, index) {
							var p = el.parentNode,
								lastElOffW = p.lastElementChild.offsetWidth,
								firstElOffL = p.firstElementChild.offsetLeft,
								w = p.offsetWidth - lastElOffW - firstElOffL - (p.offsetWidth - lastElOffW - p.lastElementChild.offsetLeft),
								tyVal = lineEq(-60, -130, firstElOffL+w, firstElOffL, el.offsetLeft);

							return tyVal+'%';
						}
					}
				},
				"fx15": {
					in: {
						duration: 400,
						delay: function(el, index) { return 100+index*50; },
						easing: 'easeOutExpo',
						opacity: 1,
						rotateX: [110,0]
					},
					out: {
						duration: 400,
						delay: function(el, index) { return index*50; },
						easing: 'easeOutExpo',
						opacity: 0,
						rotateX: -110
					}
				},
				"fx16": {
					in: {
						duration: function(el, index) { return anime.random(800,1000) },
						delay: function(el, index) { return anime.random(0,75) },
						easing: 'easeInOutExpo',
						opacity: 1,
						translateY: ['-300%','0%'],
						rotateZ: function(el, index) { return [anime.random(-50,50), 0]; }
					},
					out: {
						duration: function(el, index) { return anime.random(800,1000) },
						delay: function(el, index) { return anime.random(0,80) },
						easing: 'easeInOutExpo',
						opacity: 0,
						translateY: '300%',
						rotateZ: function(el, index) { return anime.random(-50,50); }
					}
				},
				"fx17": {
					in: {
						duration: 650,
						easing: 'easeOutQuint',
						delay: function(el, index) { return 450+(el.parentNode.children.length-index-1)*30; },
						opacity: 1,
						translateX: function(el, index) {
							return [-1*el.offsetLeft,0];
						}
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},
				"fx18": {
					in: {
						duration: 800,
						delay: function(el, index) { return 600+index*150; },
						easing: 'easeInOutQuint',
						opacity: 1,
						scaleY: [8,1],
						scaleX: [0.5,1],
						translateY: ['-100%','0%']
					},
					out: {
						duration: 800,
						delay: function(el, index) { return index*150; },
						easing: 'easeInQuint',
						opacity: 0,
						scaleY: {
							value: 8,
							delay: function(el, index) { return 100+index*150; },
						},
						scaleX: 0.5,
						translateY: '100%'
					}
				},
				"fx19": {
					in: {
						translateY: ["110%","0%"],
					    opacity: [1,1],
					    easing: "easeOutExpo",
					    duration: 500,
					    delay: (el, i) => 100 * (i+1)
					},
					out: {
						translateY: ["0%","-110%"],
					    opacity: [1,1],
					    easing: "easeOutExpo",
					    duration: 500,
					    delay: (el, i) => 100 * (i+1)
					}
				},	
				"fx20": {
					in: {
						scale: [0.3,1],
					    opacity: [0,1],
					    translateZ: 0,
					    easing: "easeOutExpo",
					    duration: 600,
					    delay: (el, i) => 70 * (i+1)
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},	
				"fx21": {
					in: {
						scale: [4,1],
					    opacity: [0,1],
					    translateZ: 0,
					    easing: "easeOutExpo",
					    duration: 950,
					    delay: (el, i) => 70*i
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},
				"fx22": {
					in: {
						opacity: [0,1],
					    easing: "easeInOutQuad",
					    duration: 1250,
					    delay: (el, i) => 70 * (i+1)
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},
				"fx23": {
					in: {
						opacity: [1,1],
						translateY: ["1.1em", 0],
					    translateZ: 0,
					    duration: 750,
					    delay: (el, i) => 50 * i
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},	
				"fx24": {
					in: {
						opacity: [1,1],
						translateY: ["1.1em", 0],
					    translateX: ["0.55em", 0],
					    translateZ: 0,
					    rotateZ: [180, 0],
					    duration: 750,
					    easing: "easeOutExpo",
					    delay: (el, i) => 50 * i
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},
				"fx25": {
					in: {
						opacity: [1,1],
						scale: [0, 1],
					    duration: 1500,
					    elasticity: 600,
					    delay: (el, i) => 45 * (i+1)
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},	
				"fx26": {
					in: {
						opacity: [1,1],
						rotateY: [-90, 0],
					    duration: 1300,
					    delay: (el, i) => 45 * i
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},	
				"fx27": {
					in: {
						opacity: [0,1],
					    easing: "easeOutExpo",
					    duration: 600,
					    offset: '-=775',
					    delay: (el, i) => 34 * (i+1)
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},
				"fx28": {
					in: {
						translateX: [40,0],
					    translateZ: 0,
					    opacity: [0,1],
					    easing: "easeOutExpo",
					    duration: 1200,
					    delay: (el, i) => 500 + 30 * i
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},	
				"fx29": {
					in: {
						translateY: [100,0],
					    translateZ: 0,
					    opacity: [0,1],
					    easing: "easeOutExpo",
					    duration: 1400,
					    delay: (el, i) => 300 + 30 * i
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},	
				"fx30": {
					in: {
						opacity: [1,1],
						translateY: [-100,0],
					    easing: "easeOutExpo",
					    duration: 1400,
					    delay: (el, i) => 30 * i
					},
					out: {
						duration: 1,
						delay: 400,
						opacity: 0
					}
				},			
			},
            t = $(this),
        	a = t.find(".text-animate > span"),
            b = a.length,
			c = effs[args.effect];
			a.each(function(i, e) {
                var p = $(e).closest(".text-animate");
                switch (args.effect) {
                	case "fx5":
                	case "fx15":
                		p.addClass("perspective-1000")
                		break;
                	case "fx9":
                	case "fx11":
                	case "fx12":
                		p.addClass("perspective-1000 transform-origin-50-100")
                		break;
                	case "fx19":
                		p.addClass("overflow-hidden")
                	case "fx20":
                	case "fx21":
                	case "fx22":
                	case "fx25":
                	case "fx26":
                	case "fx27":
                	case "fx28":
                	case "fx29":
                	case "fx30":
                		$(e).css("opacity",0)
                	case "fx23":
                	case "fx24":
                		p.addClass("overflow-hidden")
                		$(e).css("opacity",0)
                		break;
                }
            })
			// Single Text
			if ( !args.newText ) {
				c.in.targets = a.toArray(),
				anime(c.in)
			} else {
			// Multi Text
				var d = args.newText.find(".text-animate > span");
				d.each(function(i, e) {
	                var p = $(e).closest(".text-animate");
	                switch (args.effect) {
	                	case "fx5":
	                	case "fx15":
	                		p.addClass("perspective-1000")
	                		break;
	                	case "fx9":
	                	case "fx11":
	                	case "fx12":
	                		p.addClass("perspective-1000 transform-origin-50-100")
	                		break;
	                	case "fx19":
	                	case "fx23":
	                	case "fx24":
	                		p.addClass("overflow-hidden")
	                		break;
	                }
	            })
				c.in.targets = d.toArray(),
				c.out.targets = a.toArray(),
				anime(c.in)
				anime(c.out)
			}
        });
    };

    function lineEq(y2, y1, x2, x1, currentVal) {
		// y = mx + b
		var m = (y2 - y1) / (x2 - x1),
			b = y1 - m * x1;

		return m * currentVal + b;
	}
})(jQuery);