Quantcast
--[[
##############################################################################
_____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
 ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__      #
  __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____     #
   ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____    #
    ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____   #
     _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____  #
      __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ #
       _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_#
        ___\///////////___________\///___________\/////////_____\///////////_#
##############################################################################
S U P E R - V I L L A I N - U I   By: Munglunch                              #
##############################################################################

CONCEPT AND SOME CODE COURTESY OF:
##############################################################################
_____/\\\\\\\\\________/\\\\\\\\\\\\__/\\\\\\\\\\\\\\\_
 ___/\\\\\\\\\\\\\____/\\\//////////__\///////\\\/////__
  __/\\\/////////\\\__/\\\___________________\/\\\_______
   _\/\\\_______\/\\\_\/\\\____/\\\\\\\_______\/\\\_______
    _\/\\\\\\\\\\\\\\\_\/\\\___\/////\\\_______\/\\\_______
     _\/\\\/////////\\\_\/\\\_______\/\\\_______\/\\\_______
      _\/\\\_______\/\\\_\/\\\_______\/\\\_______\/\\\_______
       _\/\\\_______\/\\\_\//\\\\\\\\\\\\/________\/\\\_______
        _\///________\///___\////////////__________\///________
##############################################################################
AUTOMATIC GOBLIN THERAPIST   By: Duugu                                       #
##############################################################################
]]--

--[[ GLOBALS ]]--
local _G = _G;
local unpack    = _G.unpack;
local select    = _G.select;
local pairs     = _G.pairs;
local ipairs    = _G.ipairs;
local type      = _G.type;
local error     = _G.error;
local pcall     = _G.pcall;
local assert    = _G.assert;
local print    	= _G.print;
local tostring  = _G.tostring;
local tonumber  = _G.tonumber;
local tinsert   = _G.tinsert;
local string    = _G.string;
local math      = _G.math;
local table     = _G.table;
--[[ STRING METHODS ]]--
local lower, upper = string.lower, string.upper;
local find, format, len, split = string.find, string.format, string.len, string.split;
local match, sub, join = string.match, string.sub, string.join;
local gmatch, gsub = string.gmatch, string.gsub;
--[[ MATH METHODS ]]--
local abs, ceil, floor, round = math.abs, math.ceil, math.floor, math.round;  -- Basic
local random = math.random;  -- Uncommon
--[[ TABLE METHODS ]]--
local tremove, tcopy, twipe = table.remove, table.copy, table.wipe;
--[[
##########################################################
GET ADDON DATA
##########################################################
]]--
local PLUGIN = select(2, ...)

local Schema = PLUGIN.Schema;
local PlayersName = UnitName("player")

local SV = _G["SVUI"]
local L = SV.L
--[[
##########################################################
LOCAL VARS
##########################################################
]]--
local playerName = UnitName("player");
local playerRealm = GetRealmName();

local ConjugationKeys = {[1]={[1]="are",[2]="am",[3]="were",[4]="was",[5]="I",[6]="me",[7]="you",[8]="my",[9]="your",[10]="mine",[11]="your's",[12]="I'm",[13]="you're",[14]="I've",[15]="you've",[16]="I'll",[17]="you'll",[18]="myself",[19]="yourself"},[2]={[1]="am",[2]="are",[3]="was",[4]="were",[5]="you",[6]="you",[7]="me",[8]="your",[9]="my",[10]="your's",[11]="mine",[12]="you're",[13]="I'm",[14]="you've",[15]="I've",[16]="you'll",[17]="I'll",[18]="yourself",[19]="myself"},[3]={[1]="me am",[2]="am me",[3]="mecan",[4]="can me",[5]="me have",[6]="me will",[7]="will me"},[4]={[1]="I am",[2]="am I",[3]="I can",[4]="can I",[5]="I have",[6]="I will",[7]="will I"}};
local punctuations = {[1]={pattern="%.",value="."},[2]={pattern=",",value=","},[3]={pattern="!",value="!"},[4]={pattern="%?",value="?"},[5]={pattern=":",value=":"},[6]={pattern=";",value=";"},[7]={pattern="&",value="&"},[8]={pattern="\"",value="\""},[9]={pattern="@",value="@"},[10]={pattern="#",value="#"},[11]={pattern="%(",value="("},[12]={pattern="%)",value=")"}};

local PhoneLines = {};
local ResponseQueue = {};

local ICON_FILE = [[Interface\AddOns\SVUI_ChatOMatic\artwork\DOCK-CALL]]
local DEFAULT_GRADIENT = {"VERTICAL", 0.08, 0.08, 0.08, 0.22, 0.22, 0.22}
local GREEN_GRADIENT = {"VERTICAL", 0.08, 0.5, 0, 0.25, 0.9, 0.08}
local YELLOW_GRADIENT = {"VERTICAL", 1, 0.3, 0, 1, 1, 0}
--[[
##########################################################
DIALOG TABLES
##########################################################
]]--
local OneLiners = {
	[1] = "I've got to sit down and work out where I stand.",
	[2] = "If I save time, when do I get it back?",
	[3] = "I am not prejudice. I hate everyone equally.",
	[4] = "Take my advice, I don't use it anyway.",
	[5] = "The statement below is true. The statement above is false.",
	[6] = "As I said before, I never repeat myself.",
	[7] = "If at first you don't succeed, avoid skydiving.",
	[8] = "War doesn't determine who's right. War determines who's left.",
	[9] = "Best way to prevent a hangover is to stay drunk.",
	[10] = "Doesn't expecting the unexpected make the unexpected become the expected?",
	[11] = "I was born intelligent... education ruined me.",
	[12] = "A bus station is where a bus stops. A train station is where a train stops. On my desk, I have a work station... What more can I say?",
	[13] = "If it's true that we are here to help others, then, what exactly are the others here for?",
	[14] = "Since light travels faster than sound, people appear bright Until you hear them speak.",
	[15] = "How come \"abbreviated\" is such a long word?",
	[16] = "Living on Earth may be expensive... but it includes an annual free trip around the Sun.",
	[17] = "Your future depends on your dreams So go to sleep!",
	[18] = "A good discussion is like a miniskirt, short enough to hold interest and long enough to cover the subject.",
	[19] = "A good time to keep your mouth shut is when you are in deep water.",
	[20] = "How come we choose from just two people for President and 50 for Miss America?",
	[21] = "No one ever says \"it's just a game\" when they are winning.",
	[22] = "Suicidal twin kills sister by mistake!",
	[23] = "He who laughs last thinks slowest!",
	[24] = "Always remember you're unique, just like everyone else.",
	[25] = "Hard work has a future payoff. Laziness pays off now.",
	[26] = "Don't take life too seriously, you won't get out alive.",
	[27] = "I don't suffer from insanity. I enjoy every minute of it.",
	[28] = "I'm as confused as a baby in a topless bar.",
	[29] = "90% of all statistics are made up.",
	[30] = "If you can't convince them, confuse them.",
	[31] = "If at first you don't succeed, destroy all evidence that you tried"
}

local Excuse = {
	-- OPENERS
	[1] = "I'd love to, but ",
	[2] = "I'm being told that ",
	[3] = "The voices say that ",
	[4] = "Hang on a sec ",
	[5] = "You should know that ",
	[6] = "I just found out that ",
	[7] = "I would but ",
	[8] = "Umm... ",
	[9] = "I don't know about you but ",
	[10] = "Can't talk right now, ",
	-- PUNCHLINES
	[11] = "I have to floss my cat",
	[12] = "I've dedicated my life to linguini",
	[13] = "I want to spend more time with my blender",
	[14] = "the President said he might drop in",
	[15] = "the man on television told me to say tuned",
	[16] = "I've been scheduled for a karma transplant",
	[17] = "I'm staying home to work on my cottage cheese sculpture",
	[18] = "it's my parakeet's bowling night",
	[19] = "it wouldn't be fair to the other Beautiful People",
	[20] = "I'm building a pig from a kit",
	[21] = "I did my own thing and now I've got to undo it",
	[22] = "I'm enrolled in aerobic scream therapy",
	[23] = "there's a disturbance in the Force",
	[24] = "I'm doing door-to-door collecting for static cling",
	[25] = "I have to go to the post office to see if I'm still wanted",
	[26] = "I'm teaching my ferret to yodel",
	[27] = "I have to check the freshness dates on my dairy products",
	[28] = "I'm going through cherry cheesecake withdrawl",
	[29] = "I'm planning to go downtown to try on gloves",
	[30] = "my crayons all melted together",
	[31] = "I'm trying to see how long I can go without saying yes",
	[32] = "I'm in training to be a household pest",
	[33] = "I'm getting my overalls overhauled",
	[34] = "my patent is pending",
	[35] = "I'm attending the opening of my garage door",
	[36] = "I'm sandblasting my oven",
	[37] = "I'm worried about my vertical hold",
	[38] = "I'm going down to the bakery to watch the buns rise",
	[39] = "I'm being deported",
	[40] = "the grunion are running",
	[41] = "I'll be looking for a parking space",
	[42] = "my Millard Filmore Fan Club meets then",
	[43] = "the monsters haven't turned blue yet, and I have to eat more dots",
	[44] = "I'm taking punk totem pole carving",
	[45] = "I have to fluff my shower cap",
	[46] = "I'm converting my calendar watch from Julian to Gregorian",
	[47] = "I've come down with a really horrible case of something or other",
	[48] = "I made an appointment with a cuticle specialist",
	[49] = "my plot to take over the world is thickening",
	[50] = "I have to fulfill my potential",
	[51] = "I don't want to leave my comfort zone",
	[52] = "it's too close to the turn of the century",
	[53] = "I have some real hard words to look up in the dictionary",
	[54] = "my subconscious says no",
	[55] = "I'm giving nuisance lessons at a convenience store",
	[56] = "I left my body in my other clothes",
	[57] = "the last time I went, I never came back",
	[58] = "I've got a Friends of Rutabaga meeting",
	[59] = "I have to answer all of my 'occupant' letters",
	[60] = "none of my socks match",
	[61] = "I have to be on the next train to Bermuda",
	[62] = "I'm having all my plants neutered",
	[63] = "people are blaming me for the Spanish-American War",
	[64] = "I changed the lock on my door and now I can't get out",
	[65] = "I'm making a home movie called 'The Thing That Grew in My Refrigerator'",
	[66] = "I'm attending a perfume convention as guest sniffer",
	[67] = "my yucca plant is feeling yucky",
	[68] = "I'm touring China with a wok band",
	[69] = "my chocolate-appreciation class meets that night",
	[70] = "I never go out on days that end in 'Y'",
	[71] = "my mother would never let me hear the end of it",
	[72] = "I'm running off to Yugoslavia with a foreign-exchange student named Basil Metabolism",
	[73] = "I just picked up a book called 'Glue in Many Lands' and I can't put it down",
	[74] = "I'm too evil for that stuff",
	[75] = "I have to torment my hair",
	[76] = "I have too much guilt",
	[77] = "there are important world issues that need worrying about",
	[78] = "I have to draw 'Cubby' for an art scholarship",
	[79] = "I'm uncomfortable when I'm alone or with others",
	[80] = "I promised to help a friend fold road maps",
	[81] = "I feel a song coming on",
	[82] = "I'm trying to be less popular",
	[83] = "my bathroom tiles need grouting",
	[84] = "I have to bleach my hare",
	[85] = "I'm waiting to see if I'm already a winner",
	[86] = "I'm writing a love letter to Richard Simmons",
	[87] = "you know how we psychos are",
	[88] = "my favorite commercial is on TV",
	[89] = "I have to study for a blood test",
	[90] = "I'm going to be old someday",
	[91] = "I've been traded to Cincinnati",
	[92] = "I'm observing National Apathy Week",
	[93] = "I have to rotate my crops",
	[94] = "my uncle escaped again",
	[95] = "I'm up to my elbows in waxy buildup",
	[96] = "I have to knit some dust bunnies for a charity bazaar",
	[97] = "I'm having my baby shoes bronzed",
	[98] = "I have to go to court for kitty littering",
	[99] = "I'm going to count the bristles in my toothbrush",
	[100] = "I have to thaw some karate chops for dinner",
	[101] = "having fun gives me prickly heat",
	[102] = "I'm going to the Missing Persons Bureau to see if anyone is looking for me",
	[103] = "I have to jog my memory",
	[104] = "my palm reader advised against it",
	[105] = "my Dress For Obscurity class meets then",
	[106] = "I have to stay home and see if I snore",
	[107] = "I prefer to remain an enigma",
	[108] = "I think you want the OTHER " .. playerName,
	[109] = "I have to sit up with a sick ant",
	[110] = "I'm trying to cut down",
	[111] = ".. well, maybe",
};

local Phrases = {
	[1] = "I don't really want to<*",
	[2] = "Are you going to<*",
	[3] = "I don't know, should I<*",
	[4] = "So you are not going to<*",
	[5] = "Why don't you<*",
	[6] = "So you think I'm<*",
	[7] = "What's it to you if I'm<*",
	[8] = "Did you wanna<*",
	[9] = "Do you wanna<*",
	[10] = "Don't you really<*",
	[11] = "Why don't you<*",
	[12] = "I bet you can't<*",
	[13] = "UMADBRO?",
	[14] = "I'm marginally listening.",
	[15] = "Let me get this straight, you feel<*",
	[16] = "Stop feeling<*",
	[17] = "Why would I<*",
	[18] = "If your lucky I just might<@",
	[19] = "So, your really asking me to<*",
	[20] = "Is there a reason why YOU don't<*",
	[21] = "Why can't you<*",
	[22] = "Why are you interested in whether or not I am<*",
	[23] = "Would you prefer if I were not<*",
	[24] = "Perhaps in your fantasies I am<*",
	[25] = "How do you know you can't<*",
	[26] = "Have you tried?",
	[27] = "Perhaps you can now<*",
	[28] = "Did you come to me because you are<*",
	[29] = "How long have you been<*",
	[30] = "Do you believe it is normal to be<*",
	[31] = "Do you enjoy being<*",
	[32] = "We were discussing you, not me.",
	[33] = "Oh... <*",
	[34] = "Doesn't sound like me though, does it?",
	[35] = "How awesome would it be if you got<*",
	[36] = "Why do you want<*",
	[37] = "Suppose you got<*",
	[38] = "What if you never got<*",
	[39] = "I sometimes also want<@",
	[40] = "Whay are you asking me?",
	[41] = "Does it really matter?",
	[42] = "Is there a right answer?",
	[43] = "What do you think?",
	[44] = "You are asking the wrong questions, wanna try again?",
	[45] = "What is it that you really want to know?",
	[46] = "Who else have you asked?",
	[47] = "Am I the first person you have asked this?",
	[48] = "Don't you already know the aswer to that?",
	[49] = "The names aren't important.",
	[50] = "I won't remember any names, do continue.",
	[51] = "Is that the real reason?",
	[52] = "Don't any other reasons come to mind?",
	[53] = "Does that reason explain anything else?",
	[54] = "What other reasons might there be?",
	[55] = "Please don't apologise!",
	[56] = "Apologies are not necessary.",
	[57] = "What feelings do you have when you apologise?",
	[58] = "Don't be so defensive!",
	[59] = "What does that dream suggest to you?",
	[60] = "Do you dream often?",
	[61] = "What persons appear in your dreams?",
	[62] = "Are you disturbed by your dreams?",
	[63] = "What?",
	[64] = "You don't seem quite certain.",
	[65] = "Why the uncertain tone?",
	[66] = "Can't you be more positive?",
	[67] = "You aren't sure?",
	[68] = "Don't you know?",
	[69] = "Are you saying no just to be negative?",
	[70] = "You are being a bit negative.",
	[71] = "Why not?",
	[72] = "Are you sure?",
	[73] = "Why no?",
	[74] = "Why are you concerned about my<*",
	[75] = "What about your own<*",
	[76] = "Can you think of a specific example?",
	[77] = "When?",
	[78] = "What are you thinking of?",
	[79] = "Really, always?",
	[80] = "Think so?",
	[81] = "You thought<*",
	[82] = "You really think<*",
	[83] = "In what way?",
	[84] = "What resemblence do you see?",
	[85] = "What does the similarity suggest to you?",
	[86] = "What other connections do you see?",
	[87] = "Could there really be some connection?",
	[88] = "How?",
	[89] = "You seem quite positive.",
	[90] = "ORLY?",
	[91] = "OIC.",
	[92] = "Word.",
	[93] = "You dont have any friends.",
	[94] = "Why would I care about your friends?",
	[95] = "Are you sure you know what 'friend' means?",
	[96] = "Are you sure you have any friends?",
	[97] = "Do your friends usually get really quiet when you are around?",
	[98] = "I'm willing to bet your friends hate you.",
	[99] = "Who still uses the word noob?",
	[100] = "Are you talking about me specifically?",
	[101] = "I dunno. What are YOU doing?",
	[102] = "Would't you like to know?",
	[103] = "What do you think?",
	[104] = "I'm guessing you want something from me?",
	[105] = "I'm playing World of Warcraft... you seriously didn't know that?",
	[106] = "No kidding? Fo' realz? That's dope fresh son!",
	[107] = "And what did you learn?",
	[108] = "Gotcha.",
	[109] = "MmmmHmmm",
	[110] = "I don't follow...",
	[111] = "I'm gonna need a bit more context. Do you know what context means?",
	[112] = "Wow... just ...wow.",
	[113] = "Same question huh?",
	[114] = "Deja Vu!",
	[115] = "Yeah, lets try this again shall we?",
	[116] = "Have you recently suffered a head injury?",
	[117] = "Im hearing an echo I think....",
	[118] = "Cant all classes heal themselves now?",
	[119] = "Bandages FTW!",
	[120] = "Why are you asking me?",
	[121] = "Thats adorable how excited you are about it!",
	[122] = "What do you think?",
	[123] = "What is it that you really want to know?",
	[124] = "What is your level?",
	[125] = "Is this your first character?",
	[126] = "Most guilds are just full of high school kids with nothing better to do.",
	[127] = "What is a guild?",
	[128] = "What is the name?",
	[129] = "Oh really?",
	[130] = "Great story.",
	[131] = "Meh.",
	[132] = "No clue."
};

local Responses = {
	[1] =  {Key = "**NO KEY**",	   Question = false, Dialog = {106,107,108,109,110,111,112,129,130,131,132}},
	[2] =  {Key = "**REPEAT**",	   Question = false, Dialog = {113,114,115,116,117}},
	[3] =  {Key = "YOU'RE", 	   Question = false, Dialog = {6,7,8,9}},
	[4] =  {Key = "I DON'T", 	   Question = false, Dialog = {10,11,12,13}},
	[5] =  {Key = "I FEEL", 	   Question = false, Dialog = {14,15,16 }},
	[6] =  {Key = "WHY DON'T YOU", Question = false, Dialog = {17,18,19}},
	[7] =  {Key = "WHY CAN'T I",   Question = false, Dialog = {20,21 }},
	[8] =  {Key = "ARE YOU", 	   Question = false, Dialog = {22,23,24}},
	[9] =  {Key = "I CAN'T", 	   Question = false, Dialog = {25,26,27}},
	[10] = {Key = "I AM", 		   Question = false, Dialog = {28,29,30,31}},
	[11] = {Key = "I'M", 		   Question = false, Dialog = {28,29,30,31}},
	[12] = {Key = "YOU", 		   Question = false, Dialog = {32,33,34}},
	[13] = {Key = "I WANT", 	   Question = false, Dialog = {35,36,37,38,39 }},
	[14] = {Key = "WHAT", 		   Question = true,  Dialog = {40,41,42,43,44,45,46,47,48}},
	[15] = {Key = "HOW", 		   Question = true,  Dialog = {40,41,42,43,44,45,46,47,48}},
	[16] = {Key = "WHO", 		   Question = true,  Dialog = {40,41,42,43,44,45,46,47,48}},
	[17] = {Key = "WHERE", 		   Question = true,  Dialog = {40,41,42,43,44,45,46,47,48}},
	[18] = {Key = "WHEN", 		   Question = true,  Dialog = {40,41,42,43,44,45,46,47,48}},
	[19] = {Key = "WHY",  		   Question = true,  Dialog = {40,41,42,43,44,45,46,47,48}},
	[20] = {Key = "NAME", 		   Question = false, Dialog = {49,50}},
	[21] = {Key = "CAUSE", 		   Question = false, Dialog = {51,52,53,54}},
	[22] = {Key = "SORRY", 		   Question = false, Dialog = {55,56,57,58}},
	[23] = {Key = "DREAM",  	   Question = false, Dialog = {59,60,61,62}},
	[24] = {Key = "HELLO",  	   Question = false, Dialog = {63}},
	[25] = {Key = "HI",  		   Question = false, Dialog = {63}},
	[26] = {Key = "MAYBE",  	   Question = false, Dialog = {64,65,66,67,68}},
	[27] = {Key = "NO",   		   Question = false, Dialog = {69,70,71,72,73}},
	[28] = {Key = "YOUR",   	   Question = false, Dialog = {74,75}},
	[29] = {Key = "ALWAYS", 	   Question = false, Dialog = {76,77,78,79}},
	[30] = {Key = "THINK",  	   Question = false, Dialog = {80,81,82}},
	[31] = {Key = "ALIKE",  	   Question = false, Dialog = {83,84,85,86,87,88,89}},
	[32] = {Key = "YES",   		   Question = false, Dialog = {90,91,92}},
	[33] = {Key = "FRIEND", 	   Question = false, Dialog = {93,94,95,96,97,98}},
	[34] = {Key = "NOOB",   	   Question = false, Dialog = {99}},
	[35] = {Key = "CAN I", 		   Question = false, Dialog = {4,5}},
	[36] = {Key = "CAN YOU",  	   Question = false, Dialog = {1,2,3}},
	[37] = {Key = "WILL YOU",  	   Question = false, Dialog = {1,2,3}},
	[38] = {Key = "WOULD YOU",     Question = false, Dialog = {1,2,3}},
	[39] = {Key = "COULD YOU",     Question = false, Dialog = {1,2,3}},
	[40] = {Key = "YOU ARE", 	   Question = false, Dialog = {6,7,8,9 }},
	[41] = {Key = "HEALER",  	   Question = false, Dialog = {118,119}},
	[42] = {Key = "HOLY", 		   Question = false, Dialog = {118,119}},
	[43] = {Key = "RESTORATION",   Question = false, Dialog = {118,119}},
	[44] = {Key = "HEAL",  		   Question = false, Dialog = {118,119}},
	[45] = {Key = "PORT", 		   Question = false, Dialog = {40,41,42,43,44,45,46,47,48}},
	[46] = {Key = "PORTAL",  	   Question = false, Dialog = {40,41,42,43,44,45,46,47,48}},
	[47] = {Key = "WATER", 		   Question = false, Dialog = {40,41,42,43,44,45,46,47,48}},
	[48] = {Key = "FOOD",  		   Question = false, Dialog = {40,41,42,43,44,45,46,47,48}},
	[49] = {Key = "MONEY",  	   Question = false, Dialog = {40,41,42,43,44,45,46,47,48}},
	[50] = {Key = "GOLD", 		   Question = false, Dialog = {40,41,42,43,44,45,46,47,48}},
	[51] = {Key = "PVP",  		   Question = false, Dialog = {120,121,122,123,124,125}},
	[52] = {Key = "RAID",  		   Question = false, Dialog = {120,121,122,123,124,125}},
	[53] = {Key = "KNOW",  		   Question = false, Dialog = {64,65,66,67,68}},
	[54] = {Key = "POSSIBLE",  	   Question = false, Dialog = {64,65,66,67,68}},
	[55] = {Key = "WTF",  		   Question = false, Dialog = {64,65,66,67,68}},
	[56] = {Key = "LOL",  		   Question = false, Dialog = {64,65,66,67,68}},
	[57] = {Key = "GUILD", 		   Question = false, Dialog = {126,127,128}},
	[58] = {Key = "TOON", 		   Question = false, Dialog = {49,50}},
	[59] = {Key = "CHARACTER", 	   Question = false, Dialog = {49,50}},
	[60] = {Key = "PLAYER", 	   Question = false, Dialog = {49,50}},
	[61] = {Key = "DOING", 		   Question = false, Dialog = {100,101,102,103,104,105}},
	[62] = {Key = "UP TO", 		   Question = false, Dialog = {100,101,102,103,104,105}},
};
--[[
##########################################################
LOCAL FUNCTIONS
##########################################################
]]--
local function ServiceMessage(msg)
    local msgFrom = PLUGIN.db.prefix == true and "Minion Answering Service" or "";
    print("|cffffcc1a" .. msgFrom .. ":|r", msg)
end

local function ClearResponses(caller)
	for x = 1, #ResponseQueue, 1 do
		if ResponseQueue[x] then
			if ResponseQueue[x].CID == caller then
				tremove(ResponseQueue, x)
			end
		end
	end
end

local function RemoveCaller(caller)
	ClearResponses(caller)

	if PhoneLines[caller] then
		local data = PhoneLines[caller]
		local btn = _G["HenchmenPhoneLine"..data.Line];
		btn.Text:SetText("Empty Phone Line");
		btn:SetPanelColor("default");
		PhoneLines[caller] = nil
		ServiceMessage("Caller ("..caller..") was disconnected.");
	end
end
--[[
##########################################################
MESSAGE PROCESSING
##########################################################
]]--
do
	local function Conjugate(parse)
		for i,cj in pairs(ConjugationKeys[1]) do
			parse = gsub(parse, cj, "#@&"..i)
		end
		for i,cj in pairs(ConjugationKeys[2]) do
			parse = gsub(parse, "#@&"..i, cj)
		end
		for i,cj in pairs(ConjugationKeys[3]) do
			parse = gsub(parse, cj, "#@&"..i)
		end
		for i,cj in pairs(ConjugationKeys[4]) do
			parse = gsub(parse, "#@&"..i, cj)
		end
		return parse
	end

	local function PadString(strng)
		local aString = " "..strng.." "
		for i = 1, 12, 1 do
			aString = gsub(aString, punctuations[i].pattern, " "..punctuations[i].value.." ")
		end
		return " "..aString.." "
	end

	local function UnPadString(strng)
		local aString = strng
		aString = gsub(aString, "  ", " ")
		if sub(aString, 1, 1) == " " then
			aString = sub(aString, 2)
		end
		if sub(aString, -1, -1) == " " then
			aString = sub(aString, 1, len(aString)-1)
		end
		for i = 1, 12, 1 do
			aString = gsub(aString, " "..punctuations[i].pattern, punctuations[i].value)
		end
		return aString
	end

	local function TrimString(orgString, unpad)
		local tmpChars = ".,!?:;&\"@#()^$+-%= "
		local x = 1
		local found = true

		if(unpad) then
			orgString = UnPadString(orgString)
		end

		while found == true do
			local tchar = sub(orgString, -(x), -(x))
			if tchar == "(" or tchar == ")" or tchar == "." or tchar == "%" or tchar == "+" or tchar == "-" or tchar == "*" or tchar == "?" or tchar == "[" or tchar == "]" or tchar == "^" or tchar == "$" then
				tchar = "%"..tchar
			end
			found = find(tchar,tmpChars) and (len(orgString) - x) > 0
			x = x + 1
		end
		x = x - 1
		if (len(orgString) - x) > 0 then
			orgString = sub(orgString, 1, len(orgString) - x + 1)
		end
		x = 1
		while find(sub(orgString, x, x),tmpChars) and (len(orgString) - x) > 0 do
			x = x + 1
		end
		if (len(orgString) - x) > 0 then
			orgString = sub(orgString, x)
		end
		return orgString
	end

	local function PhraseSearch(sString, keyid, data)
		local thisstr = "";
		local phrase;
		local wordkey = Responses[keyid].Key;
		local links = Responses[keyid].Dialog;
		local idrange = #links
		if idrange > 1 then
			while(not phrase) do
				local mod = floor(random(1, idrange))
				if links[mod] ~= data.LastKey then
					phrase = Phrases[links[mod]]
					data.LastKey = links[mod]
				end
			end
		else
			data.LastKey = 1
		end
		local tempt = phrase and sub(phrase, -1, -1) or ''
		local sTemp = ""
		if tempt == "*" or tempt == "@" then
			sTemp = PadString(sString)
			local wTemp = upper(sTemp)
			local strpstr = find(wTemp, " "..wordkey.." ")
			if not strpstr then
				strpstr = find(wTemp, " "..wordkey)
			end
			if not strpstr then
				strpstr = find(wTemp, wordkey.." ")
			end
			strpstr = strpstr + len(wordkey) + 1
			thisstr = Conjugate(sub(sTemp, strpstr))
			thisstr = TrimString(thisstr, true)
			if tempt == "*" then
				sTemp = gsub(phrase, "<%*", " "..thisstr.."?")
			else
				sTemp = gsub(phrase, "<@", " "..thisstr..".")
			end
		else
			sTemp = phrase
		end
		return sTemp
	end

	local function KeywordSearch(wString)
		for k, v in gmatch(wString, "([%w']+ [%w']+ [%w']+ [%w']+ [%w']+)") do
			for x = 1, 62, 1 do
				if Responses[x].Key == k then
					return x
				end
			end
		end
		for k, v in gmatch(wString, "([%w']+ [%w']+ [%w']+ [%w']+)") do
			for x = 1, 62, 1 do
				if Responses[x].Key == k then
					return x
				end
			end
		end
		for k, v in gmatch(wString, "([%w']+ [%w']+ [%w']+)") do
			for x = 1, 62, 1 do
				if Responses[x].Key == k then
					return x
				end
			end
		end
		for k, v in gmatch(wString, "([%w']+ [%w']+)") do
			for x = 1, 62, 1 do
				if Responses[x].Key == k then
					return x
				end
			end
		end
		for k, v in gmatch(wString, "([%w]-) ") do
			for x = 1, 62, 1 do
				if Responses[x].Key == k then
					return x
				end
			end
		end
		return 1
	end

	local function MakeExcuse(sInput)
		local joke = random(100)
		if(joke <= 31) then
			return OneLiners[joke];
		end
		local word_list = {}
		for k, v in gmatch(sInput, "([%w']+)") do
			tinsert(word_list, k)
		end
		local tBestQuotes = {}
		local mxWords = 0
		for x = 11, 101, 1 do
			local count = 0
			for y = 1, #word_list, 1 do
				if find(Excuse[x], word_list[y]) then
					count = count + 1
				end
			end
			if count > mxWords then
				tBestQuotes = {}
				mxWords = count
				tinsert(tBestQuotes, x)
			elseif count == mxWords then
				tinsert(tBestQuotes, x)
			end
		end

		local response = Excuse[random(1,10)]
		local mod = random(11,101)
		if #tBestQuotes > 0 then
			mod = tBestQuotes[random(#tBestQuotes)]
		end
		response = response .. Excuse[mod]
		return response;
	end

	local function MessageBuilder(data, inbound)
		local sInput = TrimString(inbound);
		local outbound;
		local mapkey = 1;
		if sInput ~= "" and sInput ~= " " and sInput ~= "  " and sInput ~= "." and sInput ~= "," then
			local wInput = PadString(upper(sInput));
			mapkey = KeywordSearch(wInput);
			if Responses[mapkey].Question == true then
				if sub(inbound, -1, -1) ~= "?" then
					mapkey = 1
				end
			end
			if(inbound == data.InBound or inbound == data.OutBound) then
				mapkey = 2
			elseif mapkey == 1 then
				if data.FirstResponse == true then
					outbound = ":)";
				else
					if(20 >= random(100)) then
						outbound = MakeExcuse(sInput)
					end
				end
			end
			data.FirstResponse = false
		end
		if(not outbound) then
			outbound = PhraseSearch(sInput, mapkey, data)
		end
		if(PLUGIN.db.prefix == true) then
			return ("%s's Answering Service: %s"):format(PlayersName, outbound)
		else
			return outbound
		end
	end

	function PLUGIN:TakeAMessage(caller, inbound)
		ClearResponses(caller)
		local data = PhoneLines[caller];
		if(data) then
			if(data.InUse) then
				local data = PhoneLines[caller];
				local outbound = MessageBuilder(data, inbound)
				data.OutBound = outbound
				local tm = (floor(GetTime()) + ((len(outbound)/400) * 60));
				tinsert(ResponseQueue, {["ETA"] = tm, ["MSG"] = outbound, ["CID"] = caller})
			end
			data.InBound = inbound
			data.TimeStamp = GetTime()
		end
	end
end

function PLUGIN:AddCaller(caller)
	local state_text = "now on hold.";
	local call_answered = false
	PhoneLines[caller] = {
		Line = 1,
		InUse = false,
		FirstResponse = true,
		Caller = caller,
		InBound = "",
		OutBound = "",
		LastKey = 1,
		TimeStamp = 0
	};
	for x = 1, 5, 1 do
		local btn = _G["HenchmenPhoneLine"..x];
		if(btn.Text:GetText() ~= caller) then
			btn.Text:SetText(caller);
			PhoneLines[caller].Line = x
			call_answered = true
			if self.db.autoAnswer == true then
				PhoneLines[caller].InUse = true;
				btn:SetPanelColor("green");
				self.Docklet:SetPanelColor("green");
				self.Docklet.stateColor = GREEN_GRADIENT
				state_text = "on the line.";
				PlaySoundFile("Sound\\interface\\iQuestUpdate.wav")
			end
			break;
		end
	end
	if(not call_answered) then
		ServiceMessage("All lines are busy. New caller ("..caller..") was disconnected.")
	else
		ServiceMessage("New caller ("..caller..") is "..state_text)
	end
end

function PLUGIN:GetServiceState()
	local inUse = false
	local onHold = false
	for x = 1, 5, 1 do
		local btn = _G["HenchmenPhoneLine"..x];
		local caller = btn.Text:GetText()
		if(PhoneLines[caller]) then
			inUse = true
			if(not PhoneLines[caller].InUse) then
				onHold = true
			end
		end
	end

	if inUse then
		if onHold then
			self.Docklet:SetPanelColor("yellow")
			self.Docklet.Icon:SetGradient(unpack(YELLOW_GRADIENT))
			self.Docklet.stateColor = YELLOW_GRADIENT
		else
			self.Docklet:SetPanelColor("green")
			self.Docklet.Icon:SetGradient(unpack(GREEN_GRADIENT))
			self.Docklet.stateColor = GREEN_GRADIENT
		end
	else
		self.Docklet:SetPanelColor("default")
		self.Docklet.stateColor = DEFAULT_GRADIENT
	end
	return inUse,onHold
end

function PLUGIN:HangUp(caller,ignored)
	RemoveCaller(caller)
	local inUse,onHold = self:GetServiceState()

	if inUse == false then
		self.Docklet:Hide()
	elseif onHold == true then
		self.Docklet:Show()
	else
		self.Docklet:Show()
	end

	if(ignored) then
		ServiceMessage(caller.." is now ignoring you! MwaaHaHa!")
		PlaySoundFile("Sound\\interface\\RaidWarning.wav")
	end
end
--[[
##########################################################
EVENTS
##########################################################
]]--
function PLUGIN:PhoneTimeUpdate()
	local timer = 300;
	local ttime = GetTime()
	if #ResponseQueue > 0 then
		for x = 1, #ResponseQueue, 1 do
			if ResponseQueue[x] then
				if ResponseQueue[x].ETA < ttime then
					SendChatMessage(ResponseQueue[x].MSG, "WHISPER", nil, ResponseQueue[x].CID)
					tremove(ResponseQueue, x)
				end
			end
		end
	end
	if ttime > timer then
		for x = 1, 5, 1 do
			local btn = _G["HenchmenPhoneLine"..x];
			local caller = btn.Text:GetText()
			if(PhoneLines[caller]) then
				if PhoneLines[caller].TimeStamp < (ttime - timer) then
					self:HangUp(caller)
				end
			end
		end
	end
end

function PLUGIN:CHAT_MSG_IGNORED(event, inbound_message, caller, ...)
	if(PhoneLines[caller] and PhoneLines[caller].InUse) then
		self:HangUp(caller,true)
	end
end

function PLUGIN:AUTO_MSG_WHISPER(event, inbound_message, caller)
	if not UnitIsAFK("player") and not UnitIsDND("player") then
		if (not PhoneLines[caller]) then
			self:AddCaller(caller)
		end
		self:TakeAMessage(caller, inbound_message)
	end
end

function PLUGIN:AUTO_MSG_BN_WHISPER(event, inbound_message, sender, _, _, _, _, _, _, _, _, _, _, presenceID)
	if(not presenceID) then return end
	if not UnitIsAFK("player") and not UnitIsDND("player") then
		local _, bnToon = BNGetToonInfo(presenceID);
		local realToon = select(5, BNGetFriendInfoByID(presenceID))
		local caller = realToon or bnToon or sender;
		if (not PhoneLines[caller]) then
			self:AddCaller(caller)
		end
		self:TakeAMessage(caller, inbound_message)
	end
end
--[[
##########################################################
OTHER HANDLERS
##########################################################
]]--
local AnsweringOnClick = function()
	if(not PLUGIN.Docklet) then return end
	if(PLUGIN.Docklet:IsShown()) then
		PLUGIN.Docklet:Hide()
	else
		PLUGIN.Docklet:Show()
	end
end

local PhoneLineClick = function(self, button)
	local caller = self.Text:GetText()
	if((caller == "Empty Phone Line") or not PhoneLines[caller]) then return; end
	if button == "LeftButton" then
		if(not PhoneLines[caller].InUse) then
			self:SetPanelColor("green");
			PhoneLines[caller].InUse = true
			ServiceMessage("Let the torment of "..caller.." begin!")
			PLUGIN:TakeAMessage(caller, PhoneLines[caller].InBound)
		else
			self:SetPanelColor("yellow");
			PhoneLines[caller].InUse = false
			ServiceMessage(caller.." is now on hold")
		end
	elseif button == "RightButton" then
		PLUGIN:HangUp(caller)
	end
	PLUGIN:GetServiceState()
end
--[[
##########################################################
LOAD AND CONSTRUCT
##########################################################
]]--
function PLUGIN:EnableAnsweringService()
	self:RegisterEvent("CHAT_MSG_IGNORED")
	self:RegisterUpdate("PhoneTimeUpdate", 4)

	self.Docklet = SV.Dock:NewDocklet("BottomLeft", "SVUI_ChatOMaticDock", "Answering Service", ICON_FILE, AnsweringOnClick)

	local window = CreateFrame("Frame", nil, self.Docklet)
	window:SetPoint("TOPLEFT", self.Docklet, "TOPLEFT", -4, 4)
	window:SetPoint("BOTTOMRIGHT", self.Docklet, "BOTTOMRIGHT", 4, -4)
	window:SetFrameStrata("HIGH")
	window:SetPanelTemplate()

	local title = window:CreateFontString("HenchmenOperatorText")
	title:SetPoint("TOPLEFT", window, "TOPLEFT", 0, -2)
	title:SetPoint("TOPRIGHT", window, "TOPRIGHT", 0, -2)
	title:SetHeight(50)
	title:SetFontObject(GameFontNormal)
	title:SetTextColor(0.5, 0.5, 1, 1)
	title:SetJustifyH("CENTER")
	title:SetJustifyV("TOP")
	title:SetText("Henchman Answering Service")

	for x = 1, 5 do
		local phLn = CreateFrame("Button", "HenchmenPhoneLine"..x, window)
		phLn:SetPoint("TOPLEFT", window, "TOPLEFT", 8, ((-20) - (x * 25)))
		phLn:SetPoint("TOPRIGHT", window, "TOPRIGHT", -8, ((-20) - (x * 25)))
		phLn:SetHeight(20)
		phLn:RegisterForClicks("AnyUp")
		phLn:SetScript("OnClick", PhoneLineClick)
		phLn:SetFixedPanelTemplate("Button")
		phLn.Text = phLn:CreateFontString()
		phLn.Text:SetPoint("TOPLEFT", phLn, "TOPLEFT", 0, 0)
		phLn.Text:SetPoint("TOPRIGHT", phLn, "TOPRIGHT", 0, 0)
		phLn.Text:SetHeight(20)
		phLn.Text:SetFontObject(GameFontNormalSmall)
		phLn.Text:SetTextColor(1, 1, 1, 1)
		phLn.Text:SetJustifyH("CENTER")
		phLn.Text:SetJustifyV("MIDDLE")
		phLn.Text:SetText("Empty Phone Line")
	end

	self.Docklet:Hide()

	local strMsg
	if self.db.autoAnswer == true then
		strMsg = "The Henchmen Operators Are Screening Your Calls.."
	else
		strMsg = "The Henchmen Operators Are Standing By.."
	end
	SV:AddonMessage(strMsg)
	self.ServiceEnabled = true
end

function PLUGIN:DisableAnsweringService()
	self:UnregisterEvent("CHAT_MSG_IGNORED")
	self:UnregisterUpdate("PhoneTimeUpdate")
end