# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import frappe, erpnext

from frappe import _
from six import iteritems

def get_level():
	activation_level = 0
	sales_data = []
	min_count = 0
	doctypes = {
		"Asset": 5,
		"BOM": 3, 
		"Customer": 5, 
		"Delivery Note": 5,
		"Employee": 3, 
		"Instructor": 5, 
		"Instructor": 5, 
		"Issue": 5,
		"Item": 5, 
		"Journal Entry": 3, 
		"Lead": 3,
		"Leave Application": 5,
		"Material Request": 5,
		"Opportunity": 5, 
		"Payment Entry": 2, 
		"Project": 5,
		"Purchase Order": 2, 
		"Purchase Invoice": 5,
		"Purchase Receipt": 5,
		"Quotation": 3,
		"Salary Slip": 5,
		"Salary Structure": 5,
		"Sales Order": 2, 
		"Sales Invoice": 2, 
		"Stock Entry": 3,
		"Student": 5, 
		"Supplier": 5,
		"Task": 5,
		"User": 5, 
		"Work Order": 5
	}

	for doctype, min_count in iteritems(doctypes):
		count = frappe.db.count(doctype)
		if count > min_count:
			activation_level += 1
		sales_data.append({doctype: count})

	if frappe.db.get_single_value('System Settings', 'setup_complete'):
		activation_level += 1

	communication_number = frappe.db.count('Communication', dict(communication_medium='Email'))
	if communication_number > 10:
		activation_level += 1
	sales_data.append({"Communication": communication_number})

	# recent login
	if frappe.db.sql('select name from tabUser where last_login > date_sub(now(), interval 2 day) limit 1'):
		activation_level += 1

	level = {"activation_level": activation_level, "sales_data": sales_data}

	return level

def get_help_messages():
	'''Returns help messages to be shown on Desktop'''
	if get_level() > 6:
		return []

	domain = frappe.get_cached_value('Company',  erpnext.get_default_company(),  'domain')
	messages = []

	message_settings = [
		frappe._dict(
			doctype='Lead',
			title=_('Create Leads'),
			description=_('Leads help you get business, add all your contacts and more as your leads'),
			action=_('Create Lead'),
			route='List/Lead',
			domain=('Manufacturing', 'Retail', 'Services', 'Distribution'),
			target=3
		),
		frappe._dict(
			doctype='Quotation',
			title=_('Create customer quotes'),
			description=_('Quotations are proposals, bids you have sent to your customers'),
			action=_('Create Quotation'),
			route='List/Quotation',
			domain=('Manufacturing', 'Retail', 'Services', 'Distribution'),
			target=3
		),
		frappe._dict(
			doctype='Sales Order',
			title=_('Manage your orders'),
			description=_('Create Sales Orders to help you plan your work and deliver on-time'),
			action=_('Create Sales Order'),
			route='List/Sales Order',
			domain=('Manufacturing', 'Retail', 'Services', 'Distribution'),
			target=3
		),
		frappe._dict(
			doctype='Purchase Order',
			title=_('Create Purchase Orders'),
			description=_('Purchase orders help you plan and follow up on your purchases'),
			action=_('Create Purchase Order'),
			route='List/Purchase Order',
			domain=('Manufacturing', 'Retail', 'Services', 'Distribution'),
			target=3
		),
		frappe._dict(
			doctype='User',
			title=_('Create Users'),
			description=_('Add the rest of your organization as your users. You can also add invite Customers to your portal by adding them from Contacts'),
			action=_('Create User'),
			route='List/User',
			domain=('Manufacturing', 'Retail', 'Services', 'Distribution'),
			target=3
		),
		frappe._dict(
			doctype='Timesheet',
			title=_('Add Timesheets'),
			description=_('Timesheets help keep track of time, cost and billing for activites done by your team'),
			action=_('Create Timesheet'),
			route='List/Timesheet',
			domain=('Services',),
			target=5
		),
		frappe._dict(
			doctype='Student',
			title=_('Add Students'),
			description=_('Students are at the heart of the system, add all your students'),
			action=_('Create Student'),
			route='List/Student',
			domain=('Education',),
			target=5
		),
		frappe._dict(
			doctype='Student Batch',
			title=_('Group your students in batches'),
			description=_('Student Batches help you track attendance, assessments and fees for students'),
			action=_('Create Student Batch'),
			route='List/Student Batch',
			domain=('Education',),
			target=3
		),
		frappe._dict(
			doctype='Employee',
			title=_('Create Employee Records'),
			description=_('Create Employee records to manage leaves, expense claims and payroll'),
			action=_('Create Employee'),
			route='List/Employee',
			target=3
		)
	]

	for m in message_settings:
		if not m.domain or domain in m.domain:
			m.count = frappe.db.count(m.doctype)
			if m.count < m.target:
				messages.append(m)

	return messages
