from minibase.database.models import Company, Company_relation, Company_legal_entity, Company_status
from minibase.database.models import Industry, Country
from minibase.database.models import Person, Person_role, Person_competence
from minibase.database.models import Project, Project_element, Project_status, Project_note
from minibase.database.models import Product
from minibase.config import globalVars
from minibase import db
from numpy import genfromtxt

# Gets the id of company from the formated output defined at models.py for the Company Model
# The argument formatedCompanySelection is formated by SQLAlchemy in models.py files 
# Please look there before changing anything here.
def getCompanyId(formatedCompanySelection):
    text = formatedCompanySelection.split(",")
    return text[2]  # Corresponds to the ID of the Company


# Gets the id of Person's role
def getPersonRoleId(nameForId):
    selection = Person_role.query.filter_by(name=nameForId).first()
    return selection.id


# Gets the id of Person's competence
def getPersonCompetenceId(nameForId):
    selection = Person_competence.query.filter_by(name=nameForId).first()
    return selection.id


# Gets the name based on Person's id 
def getPersonName(personId):
    selection = Person.query.filter_by(id=personId).first()
    return selection


# Gets the country of the company based on it's id
def getCompanyCountry(companyId):
    selection = Company.query.filter_by(id=companyId).first()
    return selection.company_country


def getCompanyCountryId(companyId): 
    selection = Company.query.filter_by(id=companyId).first()
    return selection.country_id

# Gets the state of the company based on it's id
def getCompanyState(companyId):
    selection = Company.query.filter_by(id=companyId).first()
    return selection.street


# Gets the city of the company based on it's id
def getCompanyCity(companyId):
    selection = Company.query.filter_by(id=companyId).first()
    return selection.city


# Gets the Postal Code of the company based on it's id
def getCompanyPostCode(companyId):
    selection = Company.query.filter_by(id=companyId).first()
    return selection.post_code


# Gets the Name of the street of the company based on it's id
def getCompanyStreetName(companyId):
    selection = Company.query.filter_by(id=companyId).first()
    return selection.street


# Gets the Number of the street of the company based on it's id
def getCompanyStreetNo(companyId):
    selection = Company.query.filter_by(id=companyId).first()
    return selection.street_no


# Gets the names the all the companies
def getCompanies():
    selection = Company.query.order_by(Company.name.asc())
    return selection


def getPersonRoles():
    selection = Person_role.query.order_by(Person_role.name.asc())
    return selection


def getPersonCompetences():
    selection = Person_competence.query.order_by(Person_competence.name.asc())
    return selection


# Gets the Name of the street of the company based on it's id
def getCompanyName(companyId):
    selection = Company.query.filter_by(id=companyId).first()
    return selection.name

####################################################################################################
# Gets the Project class of based on it's id
def getProject(projectId):
    selection = Project.query.filter_by(id=projectId).first()
    return selection

def getElementIdFromProject(projectId, elementName):
    selection = Project_element.query.filter_by(project_id=projectId, name=elementName).first()
    return selection

# Gets the names the all the projects
def getProjectNames():
    selection = Project.query.order_by(Project.name.asc())
    return selection

# Gets the awailable Statuses of all the projects
def getProjectStatuses():
    selection = Project_status.query.order_by(Project_status.name.asc())
    return selection

# Gets the Name of the street of the company based on it's id
def getProjectName(projectId):
    selection = Project.query.filter_by(id=projectId).first()
    return selection.name


# Defines the selected company for the current request. This is important to fill so that some
# Templates knows if they have to show something and warns the user if no compani was selected
def setSelectedCompany(company_id):
    globalVars.selectedCompany = Company.query.filter_by(id=int(company_id)).first()


# Returns the Selected company
def getSelectedCompany():
    return Company.query.filter_by(id=globalVars.selectedCompany.id).first()


# Get the list of projects for the selected Company and if no company was selected 
# Prints an error that will be put in the selection form. 
def getProjectOfSelectedCompany():
    if globalVars.selectedCompany.id:
        selection = Project.query.filter_by(company_id=globalVars.selectedCompany.id)
        return selection
    return ["No company is selected"]


# Get the list of projects for the selected Company and if no company was selected 
# Prints an error that will be put in the selection form. 
def getEmployeesOfSelectedCompany():
    if globalVars.selectedCompany.id:
        selection = Person.query.filter_by(company_id=globalVars.selectedCompany.id)
        return selection
    return ["No company is selected"]


# Defines the selected project for the current request. This is important to fill so that some
# Templates knows if they have to show something and warns the user if no compani was selected
def setSelectedProject(project_id):
    globalVars.selectedProject = Project.query.filter_by(id=int(project_id)).first()


# Returns the Selected project
def getSelectedProject():
    return Project.query.filter_by(id=globalVars.selectedProject.id).first()


def getSelectedProjectOwner():
    if globalVars.selectedProject.id:
        selection = Project.query.filter_by(id=globalVars.selectedProject.id).first()
        return getPersonName(selection.project_responsible.id)
    return ["No Project is selected"]


def getSelectedProjectNotes():
    if globalVars.selectedProject.id:
        selection = Project_note.query.filter_by(project_id=globalVars.selectedProject.id)
        return selection
    return ["No Project is selected"]


def getSelectedElement():
    if globalVars.selectedElement.id:
        selection = Project_element.query.filter_by(id=globalVars.selectedElement.id).first()
        return selection


def getElement(element_id):
    selection = Project_element.query.filter_by(id=element_id).first()
    return selection


# Defines the selected company for the current request. This is important to fill so that some
# Templates knows if they have to show something and warns the user if no compani was selected
def setSelectedElement(element_id):
    globalVars.selectedElement = Project_element.query.filter_by(id=int(element_id)).first()


def getSelectedProjectElements():
    if globalVars.selectedProject.id:
        selection = Project_element.query.filter_by(project_id=globalVars.selectedProject.id)
        return selection


# Get the project id based on the project's name and compan's id
# As they can be project's that have the same name but corresponds to different companies.
def getProjectId(companyId, projectName):
    selection = Project.query.filter_by(company_id=companyId, name=projectName).first()
    return selection.id


# Returns the query of all awailable companie names on the table named Project
# Note that the formating is done during the SQLAlchemy Table declaration.
def person_role_choices():
    choices = Person_role.query.order_by(Person_role.name.asc())
    return choices


# Returns the query of all awailable companie names on the table named Company
# Note that the formating is done during the SQLAlchemy Table declaration.
def person_competence_choices():
    choices = Person_competence.query.order_by(Person_competence.name.asc())
    return choices


# Retunrs the qurry of all awailable industrie names on the table named Industry
# Note that the formating is done during the SQLAlchemy Table declaration.
def getIndustryNames():
    choices = Industry.query.order_by(Industry.name.asc())

    return choices


# Retunrs the query of all awailable legal entity names on the table named Company_legal_entity
# Note that the formating is done during the SQLAlchemy Table declaration.
def getCompanyLegalEntities():
    choices = Company_legal_entity.query.order_by(Company_legal_entity.name.asc())
    return choices

# Retunrs the query of all awailable legal entity names on the table named Company_legal_entity
# Note that the formating is done during the SQLAlchemy Table declaration.
def getCompanyEmployees(company_id):
    selection = Person.query.filter_by(company_id=company_id)
    return selection


# Retunrs the query of all awailable Status elements
def getCompanyStatuses():
    choices = Company_status.query.order_by(Company_status.name.asc())
    return choices


# Retunrs the query of all awailable Relation names on the table named Company_relation
# Note that the formating is done during the SQLAlchemy Table declaration.
def getCompanyRelations():
    choices = Company_relation.query.order_by(Company_relation.name.asc())
    return choices


# The Company Model has Industry Column as a foreign key and it requires the Industry's ID
# And not the name. so this function returns the right ID of the name shown at the
# Register Company Form
def getIndustryId(nameForId):
    selection = Industry.query.filter_by(name=nameForId).first()  # Gets the id of Role
    return selection.id


# The Company Model has Relation Column as a foreign key and it requires the Industry's ID
# And not the name. so this function returns the right ID of the name shown at the
# Register Company Form
def getRelationId(nameForId):
    selection = Company_relation.query.filter_by(name=nameForId).first()  # Gets the id of Role
    return selection.id


# The Company Model has Legal Entity Column as a foreign key and it requires the Industry's ID
# And not the name. so this function returns the right ID of the name shown at the
# Register Company Form
def getLegalEntityId(nameForId):
    selection = Company_legal_entity.query.filter_by(name=nameForId).first()  # Gets the id of Role
    return selection.id


# Retunrs the query of all awailable Country names on the table named Country
# Note that the formating is done during the SQLAlchemy Table declaration.
# Important note This table is ImporteD externally from a modifier SQL version of
# Github : https://github.com/dr5hn/countries-states-cities-database
def getCountryNames():
    choices = Country.query.all()
    return choices


###################################################################################################
# CSV manipulation
###################################################################################################

def openCsv(filename):
    data = genfromtxt(filename,
                      delimiter=',',
                      skip_header=1,
                      dtype=None,
                      encoding='UTF-8')
    return data.tolist()


def db_add_name_and_description(csv, table):
    try:
        csv_list = openCsv(csv)
        for i in csv_list:
            record = table(**{
                'name': i[0],
                'description': i[1]})
            db.session.add(record)  # Add all the records
        db.session.commit()  # Attempt to commit all the records
    except Exception as error:
        db.session.rollback()  # Rollback the changes on error
        print(csv)
        print("Error Ocured during <<NAME AND DESCRIPTION>> upload to DB")
        print(error)


def db_add_company(csv):
    try:
        csv_list = openCsv(csv)
        for i in csv_list:
            record = Company(**{
                'name': i[0],
                'legal_entity_id': i[1],
                'relation_id': i[2],
                'industry_id': i[3],
                'status_id': i[4],
                'website': i[5],
                'street': i[6],
                'street_no': i[7],
                'city': i[8],
                'post_code': i[9],
                'state': i[10],
                'country_id': i[11]})
            db.session.add(record)  # Add all the records
        db.session.commit()  # Attempt to commit all the records
    except Exception as error:
        db.session.rollback()  # Rollback the changes on error
        print("Error Ocured during <<COMPANY>> upload to DB")
        print(error)


def db_add_person(csv):
    try:
        csv_list = openCsv(csv)
        for i in csv_list:
            record = Person(**{
                'name': i[0],
                'last_name': i[1],
                'company_id': i[2],
                'role_id': i[3],
                'competence_id': i[4],
                'mail_prof': i[5],
                'mail_priv': i[6],
                'tel_prof_mobile': i[7],
                'street_name': i[8],
                'street_no': i[9],
                'city': i[10],
                'post_code': i[11],
                'state': i[12],
                'country_id': i[13]
                })
            db.session.add(record)  # Add all the records
        db.session.commit()  # Attempt to commit all the records
    except Exception as error:
        db.session.rollback()  # Rollback the changes on error
        print("Error Ocured during <<PERSON>> upload to DB")
        print(error)


def db_add_project(csv):
    try:
        csv_list = openCsv(csv)
        for i in csv_list:
            record = Project(**{
                'name': i[0],
                'description': i[1],
                'company_id': i[2],
                'status_id': i[3],
                'industry_id': i[4],
                'owner_id': i[5],
                'qte_prototype': i[6],
                'qte_start': i[7],
                'qte_production': i[8]
                })
            db.session.add(record)  # Add all the records
        db.session.commit()  # Attempt to commit all the records
    except Exception as error:
        db.session.rollback()  # Rollback the changes on error
        print(csv)
        print("Error Ocured during <<PROJECT>> upload to DB")
        print(error)


def db_add_project_element(csv):
    try:
        csv_list = openCsv(csv)
        for i in csv_list:
            record = Project_element(**{
                'name': i[0],
                'description': i[1],
                'qte_per_project': i[2],
                'project_id': i[3],
                'owner_id': i[4],
                'status_id': i[5],
                'company_ship_to_id': i[6]})
            db.session.add(record)  # Add all the records
        db.session.commit()  # Attempt to commit all the records
    except Exception as error:
        db.session.rollback()  # Rollback the changes on error
        print(csv)
        print("Error Ocured during <<PROJECT ELEMENT>> upload to DB")
        print(error)

def db_add_product(csv):
    try:
        csv_list = openCsv(csv)
        for i in csv_list:
            record = Product(**{
                'name': i[0],
                'ordering_code': i[1],
                'buy_cost': i[2],
                'currency': i[3],
                'description': i[4],
                'lead_time_days': i[5],
                'minimum_awarding_quantity': i[6],
                'minimum_order_quantity': i[7],
                'minimum_quote_quantity': i[8],
                'classification_id': i[9],
                'domain_id': i[10],
                'category_id': i[11],
                'sub_category_id': i[12],
                'status_id': i[13],
                'eligibility_id': i[14],
                'packaging_id': i[15],
                'physical_id': i[16],
                'manufacturer_id': i[17]})
            db.session.add(record)  # Add all the records
        db.session.commit()  # Attempt to commit all the records
    except Exception as error:
        db.session.rollback()  # Rollback the changes on error
        print(csv)
        print("Error Ocured during <<PROJECT ELEMENT>> upload to DB")
        print(error)