from .wc_object import WcObj
from .common import WcContent
from requests.exceptions import HTTPError

class WcWorkable(WcObj):
    def __init__(self, session, obj_id=None, json=None):
        super().__init__(session, obj_id, json)
        
    def checkin(self, checkin_note=None):
        action = f'PTC.{self.domain}.CheckIn'
        body = {}
        if checkin_note:
            body['CheckInNote'] = checkin_note
        response = self.session.call_api(
            request_type='post',
            domain=self.domain,
            endpoint=self.endpoint,
            arguments=self.id,
            action=action,
            body=body
        )
        self.id = response.json()['ID']
        return response

    def checkout(self):
        action = f'PTC.{self.domain}.CheckOut'
        body = {}
        response = self.session.call_api(
            request_type='post',
            domain=self.domain,
            endpoint=self.endpoint,
            arguments=self.id,
            action=action,
            body=body
        )
        self.id = response.json()['ID']
        return response

    def move(self, context_id, folder_id):
        #Not OOTB Windchill endpoint
        move_domain = 'MoveObject'
        move_endpoint = 'moveObjects'
        move_data = {'MoveInfo': {
            'ObjectID': self.id,
            'ContextID': context_id,
            'FolderID': folder_id
            } }
        response = self.session.call_api(
            request_type='post',
            domain=move_domain,
            endpoint=move_endpoint,
            body=move_data
        )
        return response

    def revise(self, new_version):
        action = f'PTC.{self.domain}.Revise'
        body = {'VersionId': new_version}
        response = self.session.call_api(
            request_type='post',
            domain=self.domain,
            endpoint=self.endpoint,
            arguments=self.id,
            action=action,
            body=body
        )
        self.id = response.json()['ID']
        return response

    def set_state(self, new_state):
        action = f'PTC.{self.domain}.SetState'
        body = {'State': {'Value': new_state}}
        response = self.session.call_api(
            request_type='post',
            domain=self.domain,
            endpoint=self.endpoint,
            arguments=self.id,
            action=action,
            body=body
        )
        self.id = response.json()['ID']
        return response
        
class WcMfrPart(WcWorkable):
    domain = 'ProdMgmt'
    endpoint = 'ManufacturerParts'
    def __init__(self, session, obj_id=None, json=None):
        super().__init__(session, obj_id, json)

class WcVendPart(WcWorkable):
    domain = 'ProdMgmt'
    endpoint = 'VendorParts'
    def __init__(self, session, obj_id=None, json=None):
        super().__init__(session, obj_id, json)
        
class WcPart(WcWorkable):
    domain = 'ProdMgmt'
    endpoint = 'Parts'
    def __init__(self, session, obj_id=None, json=None):
        super().__init__(session, obj_id, json)

    def get_desc_by_docs(self, select_str=''): #TODO: fix select_str. Currently returns an error when populated. 
        navigation = 'DescribedBy'
        expand_str = 'DescribedBy'
        part_desc_links = self.get_related(navigation, WcObj, select_str, expand_str=expand_str)
        return part_desc_links
    
    def add_desc_by_doc(self, doc):
        #Not OOTB Windchill endpoint
        action = 'DescribedBy'
        descby_body = {"DescribedBy@odata.bind" : f"Documents(\'{doc.id}\')"}

        response = self.session.call_api(
            request_type='post',
            domain=self.domain,
            endpoint=self.endpoint,
            arguments=self.id,
            action=action,
            body=descby_body
        )
        return response

    def del_desc_by_doc(self, part_desc_link):
        #Not OOTB Windchill endpoint
        action = f"DescribedBy('{part_desc_link}')"

        response = self.session.call_api(
            request_type='delete',
            domain=self.domain,
            endpoint=self.endpoint,
            arguments=self.id,
            action=action
        )
        return response

    def get_assoc_epms(self, select_str=''):
        navigation = 'PartDocAssociations'
        expand_str = 'RelatedCADDoc'
        part_doc_assocs = self.get_related(navigation, WcObj, select_str, expand_str=expand_str)
        return part_doc_assocs
    
    def add_assoc_epm(self, epm, assoc_type):
        add_assoc_endpoint = 'CreateAssociations'
        add_assoc_body = {"PartDocAssociations": [{"AssociationType":{"Value": f"{assoc_type}"}, "RelatedPart@odata.bind": f"Parts('{self.id}')", "RelatedCADDoc@odata.bind": f"CADDocuments('{epm.id}')" }]}

        response = self.session.call_api(
            request_type='post',
            domain=self.domain,
            endpoint=add_assoc_endpoint,
            body=add_assoc_body
        )
        return response
    
    def del_assoc_epm(self, epm, assoc_type):
        del_assoc_endpoint = 'DeleteAssociations'
        del_assoc_body = f'{{"PartDocAssociations": [{{"AssociationType":{{"Value": "{assoc_type}"}}, "RelatedPart@odata.bind": "Parts(\'{self.id}\')", "RelatedCADDoc@odata.bind": "CADDocuments(\'{epm.id}\')" }}]}}'

        response = self.session.call_api(
            request_type='post',
            domain=self.domain,
            endpoint=del_assoc_endpoint,
            body=del_assoc_body
        )
        return response
    
    def get_reps(self):
        navigation = 'Representations'
        objs = self.get_related(navigation, WcObj)
        return objs
        
class WcDoc(WcWorkable):
    domain = 'DocMgmt'
    endpoint = 'Documents'
    def __init__(self, session, obj_id=None, json=None):
        super().__init__(session, obj_id, json)
    
    def get_prim_content(self, select_str=''):
        navigation = 'PrimaryContent'
        obj = self.get_related_single_obj(navigation, WcContent, select_str)
        return obj
    
    def get_attachments(self, select_str=''):
        navigation = 'Attachments'
        objs = self.get_related(navigation, WcContent, select_str)
        return objs
    
    def add_prim_content(self, filename, file_bytes):
        try:
            self.del_prim_content()
        except HTTPError as e:
            pass
        response = WcContent.upload_file(
            wc_session=self.session,
            domain=self.domain,
            endpoint=self.endpoint,
            obj_id=self.id,
            filename=filename,
            file_bytes=file_bytes,
            primary_content=True
        )
        return response
        
    def del_prim_content(self):
        navigation = 'PrimaryContent'
        response = self.session.call_api(
            request_type='delete',
            domain=self.domain,
            endpoint=self.endpoint,
            arguments=self.id,
            action=navigation
        )
        return response
    
    def add_attachment(self, filename, file_bytes):
        response = WcContent.upload_file(
            wc_session=self.session,
            domain=self.domain,
            endpoint=self.endpoint,
            obj_id=self.id,
            filename=filename,
            file_bytes=file_bytes,
            primary_content=False
        )
        return response
        
class WcEpm(WcWorkable):
    domain = 'CADDocumentMgmt'
    endpoint = 'CADDocuments'
    def __init__(self, session, obj_id=None, json=None):
        super().__init__(session, obj_id, json)

    def get_reps(self):
        navigation = 'Representations'
        objs = self.get_related(navigation, WcRep)
        return objs