//
//  MessagesViewController.swift
//  MessagesExtension
//
//  Created by Julian Dunskus on 27/06/16.
//  Copyright © 2016 Julian Dunskus. All rights reserved.
//

import UIKit
import Messages

class MessagesViewController: MSMessagesAppViewController {
	
	@IBOutlet weak var loadingLabel: UILabel!
	@IBOutlet weak var cancelButton: UIButton!
	
	let baseURL = "http://dapprgames.com/pollariousURL"
	var pollController: PollViewController?
	var expansionHandler: (() -> Void)?
	
	func createLayout(from poll: Poll) -> MSMessageTemplateLayout {
		let layout = MSMessageTemplateLayout()
		layout.image = poll.pieChart(sized: CGSize(width: 900, height: 900))
		layout.imageTitle = "\(poll.voteTotal) votes"
		layout.caption = poll.question
		
		if poll.options.count > 0 { // find out the option with the majority of votes
			var chosen: Option? = poll.options[0]
			var maxCount = poll.voteCount[chosen!.id] ?? 0
			for option in poll.options.withoutFirst() {
				let count = poll.voteCount[option.id] ?? 0
				if count > maxCount {
					maxCount = count
					chosen = option
				} else if count == maxCount {
					chosen = nil
				}
			}
			if let option = chosen {
				let percentage = poll.votePercentage(for: option) * 100
				layout.subcaption = "Majority: \(option.name)"
				layout.trailingSubcaption = "(\(Int(percentage))%)"
			} else {
				layout.subcaption = "Majority: undecided"
			}
		}
		return layout
	}
	
	func createURL(from items: [URLQueryItem]) -> URL? {
		if var components = URLComponents(string: baseURL) {
			components.queryItems = items
			return components.url
		}
		return nil
	}
	
	func decodeURL(from url: URL?) -> [URLQueryItem]? {
		if let unwrapped = url {
			if let components = URLComponents(url: unwrapped, resolvingAgainstBaseURL: false) {
				return components.queryItems
			}
		}
		return nil
	}
	
	override func viewDidLoad() {
		super.viewDidLoad()
		// Do any additional setup after loading the view.
	}
	
	override func didReceiveMemoryWarning() {
		super.didReceiveMemoryWarning()
		// Dispose of any resources that can be recreated.
	}
	
	// MARK: - Conversation Handling
	
	override func willBecomeActive(with conversation: MSConversation) {
		// Called when the extension is about to move from the inactive to active state.
		// This will happen when the extension is about to present UI.
		
		// Use this method to configure the extension and restore previously stored state.
		
		print("Pollarious became active for user \(conversation.localParticipantIdentifier) and remote users:")
		for uuid in conversation.remoteParticipantIdentifiers {
			print("Remote user: \(uuid)")
		}
		
		showPollController(for: conversation.selectedMessage, in: conversation)
	}
	
	override func didResignActive(with conversation: MSConversation) {
		// Called when the extension is about to move from the active to inactive state.
		// This will happen when the user dissmises the extension, changes to a different
		// conversation or quits Messages.
		
		// Use this method to release shared resources, save user data, invalidate timers,
		// and store enough state information to restore your extension to its current state
		// in case it is terminated later.
	}
	
	override func didReceive(_ message: MSMessage, conversation: MSConversation) {
		// Called when a message arrives that was generated by another instance of this
		// extension on a remote device.
		
		// Use this method to trigger UI updates in response to the message.
		if conversation.selectedMessage != nil && message.session == conversation.selectedMessage!.session {
			
		}
	}
	
	override func didStartSending(_ message: MSMessage, conversation: MSConversation) {
		// Called when the user taps the send button.
		dismiss()
	}
	
	override func didCancelSending(_ message: MSMessage, conversation: MSConversation) {
		// Called when the user deletes the message without sending it.
		
		// Use this to clean up state related to the deleted message.
	}
	
	override func willTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
		// Called before the extension transitions to a new presentation style.
		
		// Use this method to prepare for the change in presentation style.
	}
	
	override func didTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
		// Called after the extension transitions to a new presentation style.
		
		// Use this method to finalize any behaviors associated with the change in presentation style.
		pollController?.tableView.reloadData()
		
		if presentationStyle == .expanded {
			expansionHandler?()
			expansionHandler = nil
		}
	}
	
	override func didSelect(_ message: MSMessage, conversation: MSConversation) {
		pollController?.dismiss(animated: false) {
			self.showPollController(for: message, in: self.activeConversation!)
		}
	}
	
	@IBAction func cancelPressed() {
		if let controller = pollController {
			present(controller, animated: true, completion: nil)
			return
		}
	}
	
	func showPollController(for message: MSMessage?, in conversation: MSConversation, animated: Bool = true) {
		if let items = decodeURL(from: message?.url) {
			let poll = Poll(from: items)
			showPollController(for: poll, in: conversation, animated: animated)
		} else {
			showPollController(for: Poll(), in: conversation, animated: animated)
		}
	}
	
	func showPollController(for poll: Poll, in conversation: MSConversation, animated: Bool = true) {
		if let viewController = storyboard?.instantiateViewController(withIdentifier: "Poll") as? PollViewController {
			pollController = viewController
			viewController.poll = poll
			viewController.userUUID = conversation.localParticipantIdentifier
			viewController.messagesController = self
			present(viewController, animated: animated, completion: nil)
		} else {
			fatalError("Could not instantiate Poll View Controller!")
		}
	}
	
	func poll(_ poll: Poll, didFinishEditingWithChoice choice: Int) {
		guard let conversation = activeConversation else {
			print("No active conversation!")
			return
		}
		
		let previous = conversation.selectedMessage
		let session = previous?.session ?? MSSession()
		let decoded = decodeURL(from: previous?.url)
		let prevPoll: Poll? = decoded != nil ? Poll(from: decoded!) : nil
		
		let change = decoded?[0].value ?? ""
		
		let message = MSMessage(session: session)
		message.layout = createLayout(from: poll)
		
		var changeDesc = "Poll Created: \(poll.question)"
		
		let uuid = conversation.localParticipantIdentifier
		if let prevVote = prevPoll?.votes[uuid] {
			if let newVote = poll.votes[uuid] {
				changeDesc = prevVote == newVote ? "Didn't vote" : "Changed vote"
			} else {
				changeDesc = "Removed vote"
			}
		} else {
			changeDesc = "Voted"
		}
		if prevPoll != nil && !(prevPoll! == poll) {
			changeDesc = "\(changeDesc) and modified the poll"
		}
		
		var items = [URLQueryItem(name: "change", value: changeDesc)]
		items.append(contentsOf: poll.toQueryItems())
		message.url = createURL(from: items)
		
		conversation.insert(message, localizedChangeDescription: change) { (error) in
			print(error?.localizedDescription)
		}
		requestPresentationStyle(.compact)
		
		loadingLabel.text = "Please send the message."
		cancelButton.isHidden = false
	}
}

extension MessagesViewController: UITextFieldDelegate {
	
	func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
		if presentationStyle == .compact {
			expansionHandler = {
				textField.becomeFirstResponder() // automatically start editing once expanded
			}
			requestPresentationStyle(.expanded)
		}
		return true
	}
}
