import discord
import PIL.Image
import numpy as np
from io import BytesIO
from discord.ext import commands
from wordcloud import WordCloud, ImageColorGenerator
from mods.cog import Cog

class Wc(Cog):
	def __init__(self, bot):
		super().__init__(bot)
		self.bytes_download = bot.bytes_download
		self.isimage = bot.isimage
		self.cursor = bot.mysql.cursor
		self.get_images = bot.get_images
		self.message_cache = {}

	def make_wc(self, text, max):
		try:
			wc = WordCloud(background_color='black', width=1024, height=768, max_words=max).generate(' '.join(text))
			img = wc.to_image()
			b = BytesIO()
			img.save(b, 'png')
			b.seek(0)
			return b
		except Exception as e:
			return str(e)

	def make_wc_custom(self, mask, text, max):
		try:
			coloring = np.array(PIL.Image.open(mask))
			wc = WordCloud(width=1024, height=768, max_words=max, mask=coloring)
			wc = wc.generate(' '.join(text))
			image_colors = ImageColorGenerator(coloring)
			wc = wc.recolor(color_func=image_colors)
			img = wc.to_image()
			b = BytesIO()
			img.save(b, 'png')
			b.seek(0)
			return b
		except Exception as e:
			return str(e)

	async def get_messages(self, channel, limit, user=None):
		msgs = None
		if channel in self.message_cache.keys():
			msgs = self.message_cache[channel]
			if len(msgs) >= limit:
				msgs = msgs[:limit]
			else:
				before = msgs[-1]
				limit = limit-len(msgs)
		else:
			self.message_cache[channel] = []
			before = None
		if not msgs:
			async for message in self.bot.logs_from(channel, limit=limit, before=before):
				self.message_cache[channel].append(message.content)
			msgs = self.message_cache[channel]
			if not len(msgs):
				return ['no messages found rip']
		final = []
		for msg in msgs:
			final.extend([*msg.split()])
		return final

	@commands.group(pass_context=True, name='wc', aliases=['wordcloud', 'wordc'], invoke_without_command=True)
	@commands.cooldown(10, 1)
	async def wc(self, ctx, *urls:str):
		max_messages = 500
		custom = False
		if len(urls) == 1:
			if urls[0].isdigit():
				max_messages = int(urls[0])
		elif len(urls) > 1:
			get_images = await self.get_images(ctx, urls=urls, scale=4000)
			if not get_images:
				return
			custom = True
			image, scale, scale_msg = get_images
			image = await self.bytes_download(image[0])
			if scale:
				max_messages = int(scale)
		if max_messages > 4000 or max_messages < 1:
			max_messages = 500
		x = await self.bot.say("ok, processing{0}".format(' (this might take a while)' if max_messages > 2000 else ''))				
		text = await self.get_messages(ctx.message.channel, max_messages)
		if custom:
			b = await self.bot.loop.run_in_executor(None, self.make_wc_custom, image, text, max_messages)
		else:
			b = await self.bot.loop.run_in_executor(None, self.make_wc, text, max_messages)
		if type(b) == str:
			await self.bot.say(b)
		else:
			await self.bot.upload(b, filename='wordcloud.png')
		await self.bot.delete_message(x)

	@wc.command(name='user', pass_context=True, aliases=['u'])
	@commands.cooldown(10, 1)
	async def wc_user(self, ctx, user:discord.User, max_messages:int=500):
		if max_messages > 4000 or max_messages < 1:
			max_messages = 500
		x = await self.bot.say("ok, processing{0}".format(' (this might take a while)' if max_messages > 2000 else ''))				
		text = await self.get_messages(ctx.message.channel, max_messages, user=user.id)
		b = await self.bot.loop.run_in_executor(None, self.make_wc, text, max_messages)
		await self.bot.upload(b, filename='wordcloud.png')
		await self.bot.delete_message(x)

def setup(bot):
	bot.add_cog(Wc(bot))