# flake8: noqa: E501
from cruxctl.common.api.rest_client import RestAPI


class CruxApiV2Ops(RestAPI):
    """
    https://api.cruxinformatics.com/v2/ops/swagger/ops-v2.json
    """

    def __init__(self, url, *args, **kwargs):
        kwargs.setdefault("api_root", "")
        kwargs.setdefault("api_version", "v2/ops")
        super().__init__(url, *args, **kwargs)

    def whoami(self):
        """
        Get identity by API key.
        See https://api.cruxinformatics.com/v2/ops/swagger#/identities/getV2OpsIdentitiesProfileApikey
        :return:
        """

        url = self.resource_url("identities")
        return self.get(f"{url}/profile/api-key")

    def get_orgs(self, filter_query=None, offset=0, limit=100):
        """
        Gets org by its id
        See https://api.cruxinformatics.com/v2/ops/swagger#/orgs/getV2OpsOrgsId
        :param filter_query: (e.g., Orks5Xgf)
        :param offset:
        :param limit:
        :return:
        Example
        ```
        [
          {
            "createdAt": "2020-11-05T18:22:41.264+00:00",
            "modifiedAt": "2020-11-05T18:22:41.264+00:00",
            "id": "OrsqJpxT",
            "legacyId": "IQGsqJpxTE_D51wvpZICTY05xw",
            "type": "supplier",
            "code": "CHRCOM",
            "name": "Charity Commission for England and Wales",
            "description": "The Charity Commission for England and Wales is ...",
            "website": "https://www.gov.uk/government/organisations/charity-commission",
            "markedComplete": false,
            "externalId": "CXO23732",
            "attr": {
              "ftz": false,
              "display": true,
              "clientName": "",
              "legalDetails": "",
              "publicPolicy": "Use case is permitted, but attribution is required...",
              "supplierType": "Public",
              "documentation": "",
              "supplierStatus": true,
              "kycDocumentation": "",
              "vendorCollateral": "",
              "supplierContracts": "",
              "excludeFromMarketing": false,
              "onboardingDocumentation": "",
              "subcontractorThirdParty": "Third Party Allowed"
            }
          },
          {
            "createdAt": "2021-01-07T20:56:05.348+00:00",
            "modifiedAt": "2021-01-07T20:56:05.348+00:00",
            "id": "OrGWP8PP",
            "legacyId": "IQHGWP8PPAE8hLNdME5QavSqhw",
            "type": "supplier",
            "code": "DJI",
            "name": "Dow Jones",
            "description": "Dow Jones brings together world-leading data, media, ...",
            "website": "http://www.dowjones.com",
            "markedComplete": false,
            "externalId": "CXO67351",
            "attr": {
              "ftz": false,
              "zip": "",
              "city": "New York",
              "state": "NY",
              "address": "",
              "country": "United States",
              "display": true,
              "clientName": "",
              "legalDetails": "",
              "publicPolicy": "",
              "supplierType": "Client Proprietary",
              "documentation": "https://drive.google.com/drive/folders/1kWRBkeHNhNAyelHpgWSkQ1NLNCZvWtIG",
              "supplierStatus": true,
              "supportAddress": "",
              "kycDocumentation": "",
              "vendorCollateral": "",
              "supplierContracts": "",
              "excludeFromMarketing": false,
              "onboardingDocumentation": "",
              "subcontractorThirdParty": "Third Party Allowed"
            }
          }
        ]
        ```
        """

        params = {}
        if filter_query:
            params["filter"] = filter_query
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("orgs")
        return self.get(url, params=params)

    def get_org(self, org_id):
        """
        Gets org by its id
        See https://api.cruxinformatics.com/v2/ops/swagger#/orgs/getV2OpsOrgsId
        :param org_id: Organization identifier (e.g., Orks5Xgf)
        :return:
        """

        url = self.resource_url("orgs")
        return self.get(f"{url}/{org_id}")

    def get_datasets(self, filter_query=None, offset=0, limit=100, filter_by_org=False):
        """
        Gets a list of datasets.
        See https://api.cruxinformatics.com/v2/ops/swagger#/datasets/getV2OpsDatasets
        :param filter_query: (e.g., workflowId.eq.stlouisfed_willlrgcap)
        :param offset:
        :param limit:
        :param filter_by_org:
        :return:
        Example
        ```
        [
          {
            "id": "DsKe3_82",
            "legacyId": "AQIKe3_82I5RSKaUg43q2wYQtA",
            "name": "STLOUISFED_WILLLRGCAP_API",
            "description": " ",
            "workflowId": "stlouisfed_willlrgcap",
            "ownerIdentityId": "Orn0UMd5",
            "contactIdentityId": "IQHn0UMd5-ND9g51beQ19torqA",
            "cronSchedule": "@daily",
            "publicDs": false,
            "approved": false,
            "bucketName": "com-crux-6d9c155fbbf48156c6eb7f63b46c784b",
            "bucketLocation": "US",
            "status": "Done",
            "createdAt": "2020-03-25T17:26:26.000+00:00",
            "modifiedAt": "2020-03-25T17:26:26.000+00:00"
          }
        ]
        ```
        """

        params = {}
        if filter_query:
            params["filter"] = filter_query
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        if filter_by_org is not None:
            params["filterByOrg"] = filter_by_org
        url = self.resource_url("datasets")
        return self.get(url, params=params)

    def get_dataset(self, dataset_id, filter_by_org=False):
        """
        Gets dataset by its id.
        See https://api.cruxinformatics.com/v2/ops/swagger#/datasets/getV2OpsDatasetsId
        :param dataset_id: Dataset identifier (e.g., Ds003GiV or AQI003GiV6d1fjKxJ6_cVP_ijA)
        :param filter_by_org:
        :return:
        """

        params = {}
        if filter_by_org is not None:
            params["filterByOrg"] = filter_by_org
        url = self.resource_url("datasets")
        return self.get(f"{url}/{dataset_id}", params=params)

    def create_dataset(self, data):
        """
        Creates a new dataset
        See https://api.cruxinformatics.com/v2/ops/swagger#/datasets/postV2OpsDatasets
        :param data:
        Example
        ```
        {
          "ownerIdentityId": "Orn0UMd5",
          "workflowId": "stlouisfed_othl1t5",
          "name": "St Louis Federal Bank - OTHL1T5"
        }
        ```
        :return:
        Example
        ```
        {
          "attachments": [],
          "bucketLocation": "US",
          "bucketName": "com-crux-81b9bec042605eb24916799fbe794e07",
          "createdAt": "2023-08-16T21:34:03.430+00:00",
          "description": "",
          "id": "Ds5-Melp",
          "legacyId": "AQK5-Melpb_r9IwSDoF2y4Zbhw",
          "modifiedAt": "2023-08-16T21:34:03.430+00:00",
          "name": "St Louis Federal Bank - OTHL1T5",
          "ownerIdentityId": "Orn0UMd5",
          "status": "In Progress",
          "tags": [],
          "timezone": "UTC",
          "workflowId": "stlouisfed_othl1t5"
        }
        ```
        """

        url = self.resource_url("datasets")
        return self.post(url, json=data)

    def create_bulk_datasets(self, data):
        """
        Creates a list of datasets
        See https://api.cruxinformatics.com/v2/ops/swagger#/datasets/putV2OpsDatasets
        :param data:
        Example
        ```
        [
          {
            "ownerIdentityId": "Orn0UMd5",
            "workflowId": "stlouisfed_othl1t5",
            "name": "St Louis Federal Bank - OTHL1T5"
          },
        ]
        ```
        :return:
        Example
        ```
        [
          {
            "attachments": [],
            "bucketLocation": "US",
            "bucketName": "com-crux-81b9bec042605eb24916799fbe794e07",
            "createdAt": "2023-08-16T21:34:03.430+00:00",
            "description": "",
            "id": "Ds5-Melp",
            "legacyId": "AQK5-Melpb_r9IwSDoF2y4Zbhw",
            "modifiedAt": "2023-08-16T21:34:03.430+00:00",
            "name": "St Louis Federal Bank - OTHL1T5",
            "ownerIdentityId": "Orn0UMd5",
            "status": "In Progress",
            "tags": [],
            "timezone": "UTC",
            "workflowId": "stlouisfed_othl1t5"
          },
        ]
        ```
        """

        url = self.resource_url("datasets")
        return self.put(url, json=data)

    def update_dataset(self, dataset_id, data):
        """
        Updates dataset specified by its id.
        See https://api.cruxinformatics.com/v2/ops/swagger#/datasets/putV2OpsDatasetsId
        :param dataset_id: Dataset identifier (e.g., Ds5-Melp)
        :param data:
        Example
        ```
        {
          "name": "St Louis Federal Bank - OTHL1T5 (updated)"
        }
        ```
        :return:
        Example
        ```
        {
          "attachments": [],
          "bucketLocation": "US",
          "bucketName": "com-crux-81b9bec042605eb24916799fbe794e07",
          "createdAt": "2023-08-16T21:34:03.430+00:00",
          "description": "",
          "id": "Ds5-Melp",
          "legacyId": "AQK5-Melpb_r9IwSDoF2y4Zbhw",
          "modifiedAt": "2023-08-16T21:34:03.430+00:00",
          "name": "St Louis Federal Bank - OTHL1T5 (updated)",
          "ownerIdentityId": "Orn0UMd5",
          "status": "In Progress",
          "tags": [],
          "timezone": "UTC",
          "workflowId": "stlouisfed_othl1t5"
        }
        ```
        """

        url = self.resource_url("datasets")
        return self.put(f"{url}/{dataset_id}", json=data)

    def delete_dataset(self, dataset_id, mode="SOFT"):
        """
        Deletes dataset specified by its id
        See https://api.cruxinformatics.com/v2/ops/swagger#/datasets/deleteV2OpsDatasetsId
        :param dataset_id: Dataset identifier (e.g., Ds5-Melp)
        :param mode: (SOFT, DATA, HARD)
        :return:
        """

        params = {}
        if mode:
            params["mode"] = mode
        url = self.resource_url("datasets")
        return self.delete(f"{url}/{dataset_id}", params=params)

    def get_frames(self, filter_query=None, offset=0, limit=100, filter_by_org=False):
        """
        Gets a list of frames
        See https://api.cruxinformatics.com/v2/ops/swagger#/frames/getV2OpsFrames
        :param filter_query: (e.g., datasetId.eq.DsSExyAK)
        :param offset:
        :param limit:
        :param filter_by_org:
        :return:
        Example
        ```
        [
          {
            "id": "FrSExyAKda3dfd",
            "frameId": "Wrangle_ESG_RATINGS_COVERED",
            "datasetId": "DsSExyAK",
            "workflowId": "Wrangle_ESG_RATINGS_COVERED",
            "frameGroup": "CRUX_GENERAL",
            "name": "Wrangle_ESG_RATINGS_COVERED",
            "type": "basic",
            "status": "GENERATED",
            "description": "MSCI ESG Wrangle for Ratings Covered",
            "remotePath": "",
            "fetchedFile": "",
            "unzippedFile": "",
            "optional": false,
            "emptyFileOk": false,
            "acceptsMultiple": false,
            "createdAt": "2021-07-15T19:06:28.480+00:00",
            "modifiedAt": "2021-07-15T19:06:28.480+00:00"
          },
        ]
        ```
        """

        params = {}
        if filter_query:
            params["filter"] = filter_query
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        if filter_by_org is not None:
            params["filterByOrg"] = filter_by_org
        url = self.resource_url("frames")
        return self.get(url, params=params)

    def get_frame(self, frame_id, filter_by_org=False):
        """
        Gets frame by its id
        See https://api.cruxinformatics.com/v2/ops/swagger#/frames/getV2OpsFramesId
        :param frame_id: Frame identifier (e.g., FrvbWvtPba6cad)
        :param filter_by_org:
        :return:
        """

        params = {}
        if filter_by_org is not None:
            params["filterByOrg"] = filter_by_org
        url = self.resource_url("frames")
        return self.get(f"{url}/{frame_id}", params=params)

    def create_frame(self, data):
        """
        Creates a new frame
        See https://api.cruxinformatics.com/v2/ops/swagger#/frames/postV2OpsFrames
        :param data:
        Example
        ```
        {
          "frameId": "test_frame",
          "datasetId": "DsHTFOQ0",
          "name": "test_workflow",
          "workflowId": "test_workflow",
          "frameGroup": "CRUX_GENERAL"
        }
        ```
        :return:
        Example
        ```
        {
          "createdAt": "2023-08-18T19:03:00.245+00:00",
          "datasetId": "DsHTFOQ0",
          "frameGroup": "CRUX_GENERAL",
          "frameId": "test_frame",
          "id": "FrHTFOQ0794d47",
          "modifiedAt": "2023-08-18T19:03:00.245+00:00",
          "name": "test_workflow",
          "status": "DEV",
          "type": "basic",
          "workflowId": "test_workflow"
         }
        ```
        """

        url = self.resource_url("frames")
        return self.post(url, json=data)

    def create_bulk_frames(self, data):
        """
        Creates a list of frames
        See https://api.cruxinformatics.com/v2/ops/swagger#/frames/putV2OpsFrames
        :return:
        """

        url = self.resource_url("frames")
        return self.put(url, json=data)

    def update_frame(self, frame_id, data):
        """
        Update Frame
        See https://api.cruxinformatics.com/v2/ops/swagger#/frames/putV2OpsFramesId
        :param frame_id: Frame identifier (e.g., FrHTFOQ0794d47)
        :param data:
        ```
        Example
        {
          "description": "sample_value"
        }
        ```
        :return:
        """

        url = self.resource_url("frames")
        return self.put(f"{url}/{frame_id}", json=data)

    def delete_frame(self, frame_id):
        """
        Deletes frame specified by its id
        See https://api.cruxinformatics.com/v2/ops/swagger#/frames/deleteV2OpsFramesId
        :param frame_id: Frame identifier (e.g., FrHTFOQ0794d47)
        :return:
        """

        url = self.resource_url("frames")
        return self.delete(f"{url}/{frame_id}")

    def create_cdu(self, data):
        """
        Creates a new cdu
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdus/postV2OpsCdus
        :param data: Crux Delivery Unit information
        ```
        Examples:
        {
          "name": "Test CDU",
          "ownerIdentityId": "OrU5GcbJ"
        }

        {
          "name": "Test CDU",
          "description": "This is a TEST CDU",
          "type": "Product",
          "assetClass": "Energy",
          "attributes": {
            "historyEnabled": False,
            "discoverListing": True
          },
          "billingTier": "Band 5",
          "common": True,
          "country": "China",
          "dataCategory": "OWNERSHIP",
          "marketVertical": "FINANCIAL",
          "mutualizable": True,
          "ownerIdentityId": "OrU5GcbJ",
          "productFamily": "Test",
          "region": "Americas",
          "sourceCategory": "",
          "sourceType": "Public"
        }
        ```
        :return:
        Example
        ```
        {
           "assetClass": "Energy",
           "attributes": {"discoverListing": True, "historyEnabled": False},
           "billingTier": "Band 5",
           "code": "cx18863",
           "common": True,
           "country": "China",
           "createdAt": "2023-08-16T21:08:51.379+00:00",
           "dataCategory": "OWNERSHIP",
           "description": "This is a TEST CDU",
           "id": "Cx18863",
           "marketVertical": "FINANCIAL",
           "modifiedAt": "2023-08-16T21:08:51.379+00:00",
           "mutualizable": "true",
           "name": "Test CDU",
           "ownerIdentityId": "OrU5GcbJ",
           "productFamily": "Test",
           "region": "Americas",
           "sourceCategory": "",
           "sourceType": "Public",
           "type": "Product"
        }
        ```
        """

        url = self.resource_url("cdus")
        return self.post(url, json=data)

    def create_bulk_cdus(self, data):
        """
        Creates a list of cdus
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdus/putV2OpsCdus
        :param data: A list of Crux Delivery Unit information dictionary
        ```
        Examples:
        [
          {
            "name": "Test CDU",
            "description": "This is a TEST CDU",
            "type": "Product",
            "assetClass": "Energy",
            "attributes": {
              "historyEnabled": False,
              "discoverListing": True
            },
            "billingTier": "Band 5",
            "common": True,
            "country": "China",
            "dataCategory": "OWNERSHIP",
            "marketVertical": "FINANCIAL",
            "mutualizable": True,
            "ownerIdentityId": "OrU5GcbJ",
            "productFamily": "Test",
            "region": "Americas",
            "sourceCategory": "",
            "sourceType": "Public"
          },
        ]
        ```
        :return:
        Example
        ```
        {
           "assetClass": "Energy",
           "attributes": {"discoverListing": True, "historyEnabled": False},
           "billingTier": "Band 5",
           "code": "cx18863",
           "common": True,
           "country": "China",
           "createdAt": "2023-08-16T21:08:51.379+00:00",
           "dataCategory": "OWNERSHIP",
           "description": "This is a TEST CDU",
           "id": "Cx18863",
           "marketVertical": "FINANCIAL",
           "modifiedAt": "2023-08-16T21:08:51.379+00:00",
           "mutualizable": "true",
           "name": "Test CDU",
           "ownerIdentityId": "OrU5GcbJ",
           "productFamily": "Test",
           "region": "Americas",
           "sourceCategory": "",
           "sourceType": "Public",
           "type": "Product"
        }
        ```
        """

        url = self.resource_url("cdus")
        return self.put(url, json=data)

    def update_cdu(self, cdu_id, data):
        """
        Updates cdu specified by its id.
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdus/putV2OpsCdusId
        :param cdu_id: Crux Delivery Unit identifier (e.g., Cx23622)
        :param data:
        Example
        ```
        {
          "name": "Test CDU (updated)"
        }
        ```
        :return:
        """

        url = self.resource_url("cdus")
        return self.put(f"{url}/{cdu_id}", json=data)

    def delete_cdu(self, cdu_id):
        """
        Deletes cdu specified by its id
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdus/deleteV2OpsCdusId
        :param cdu_id: Crux Delivery Unit identifier (e.g., Cx12378)
        :return:
        """

        url = self.resource_url("cdus")
        return self.delete(f"{url}/{cdu_id}")

    def get_cdu_packages(self, filter_query=None, offset=0, limit=100):
        """
        Gets a list of cdu packages
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-packages/getV2OpsCdupackages
        :return:
        Example
        ```
        [
          {
            "id": "Cx01882",
            "cduIds": [
              "Cx01296",
              "Cx01412",
              "Cx01446",
              "Cx01447",
              "Cx01448",
              "Cx01449",
              "Cx01450",
              "Cx01451",
              "Cx01452",
            ],
            "createdAt": "2020-07-21T16:29:42.759+00:00",
            "modifiedAt": "2020-07-21T16:29:42.759+00:00"
          },
        ]
        ```
        """

        params = {}
        if filter_query:
            params["filter"] = filter_query
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("cdupackages")
        return self.get(url, params=params)

    def get_cdu_maps(self, filter_query=None, offset=0, limit=10000):
        """
        Gets a list of cdu-maps
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-maps/getV2OpsCdumaps
        :param filter_query: (e.g., cduId.eq.Cx20624)
        :param offset:
        :param limit:
        :return:
        Example
        ```
        [
          {
            "cduId": "Cx05990",
            "datasetId": "Ds8NPR-3",
            "createdAt": "2020-05-16T01:55:05.152+00:00"
          },
          {
            "cduId": "Cx06315",
            "datasetId": "DsykCvO6",
            "createdAt": "2020-05-16T01:55:05.152+00:00"
          },
          {
            "cduId": "Cx05576",
            "datasetId": "DsMqgeO-",
            "createdAt": "2020-05-16T01:55:05.152+00:00"
          },
        ]
        ```
        """

        params = {}
        if filter_query:
            params["filter"] = filter_query
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("cdumaps")
        return self.get(url, params=params)

    def get_dataset_cdu(self, dataset_id, offset=0, limit=100):
        """
        Gets all cdus that have this dataset
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-maps/getV2OpsCdumapsDatasetidCdus
        :param dataset_id: Dataset identifier (e.g., AQKgLm9fZZpr5GM8Sti84Vd-iQ)
        :param offset:
        :param limit:
        :return:
        Example
        ```
        [
            {
                "id": "Cx20336",
                "name": "Form EIA-923 Data",
                "code": "cx20336",
                "productFamily": "EIA - Electricity Data",
                "description": "The survey Form EIA-923 collects detailed electric power data ",
                "type": "Product",
                "sensitive": false,
                "common": false,
                "display": "false",
                "orgCode": "EIA",
                "ownerIdentityId": "OrY3WKnc",
                "sourceType": "Public",
                "marketVertical": "ALTERNATIVE",
                "assetClass": "Energy",
                "region": "Americas",
                "country": "United States of America",
                "jiraKey": "DS-52071",
                "mutualizable": "true",
                "dataCategory": "ESG",
                "attributes": {
                    "displayNotes": "TS deemed sensitive",
                    "historyEnabled": false,
                    "discoverListing": false,
                    "containsCusipSedol": "no"
                },
                "createdAt": "2022-05-25T16:12:36.299+00:00",
                "modifiedAt": "2022-05-25T16:12:36.299+00:00"
            }
        ]
        ```
        """

        params = {}
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("cdumaps")
        return self.get(f"{url}/{dataset_id}/cdus", params=params)

    def get_datasets_in_a_cdu(self, cdu_id, offset=0, limit=1000):
        """
        Gets all datasets that belong to a cdu
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-maps/getV2OpsCdumapsCduidDatasets
        :param cdu_id: Crux Delivery Unit identifier (e.g., Cx20336)
        :param offset:
        :param limit:
        :return:
        Example
        ```
        [
            {
                "id": "DsgLm9fZ",
                "legacyId": "AQKgLm9fZZpr5GM8Sti84Vd-iQ",
                "name": "us_eia_form_eia_923_data_history",
                "description": "",
                "workflowId": "us_eia_form_eia_923_data_history",
                "ownerIdentityId": "IQEY3WKncGbfXhGJN1K7KM0OWg",
                "cronSchedule": "@once",
                "publicDs": false,
                "approved": false,
                "afVar": "US_EIA_FORM_EIA_923_DATA_HISTORY_API",
                "tags": [],
                "createdAt": "2022-07-04T13:13:42.524+00:00",
                "modifiedAt": "2022-07-08T03:15:52.213+00:00"
            },
            {
                "id": "DsoMwNLi",
                "legacyId": "AQLoMwNLiQNypFRmB2dwS2Zf3g",
                "name": "us_eia_form_eia_923_data_ongoing",
                "description": "",
                "workflowId": "us_eia_form_eia_923_data_ongoing",
                "ownerIdentityId": "IQEY3WKncGbfXhGJN1K7KM0OWg",
                "cronSchedule": "0 20 25-31 * *",
                "publicDs": false,
                "approved": false,
                "afVar": "US_EIA_FORM_EIA_923_DATA_ONGOING_API",
                "tags": [],
                "createdAt": "2022-07-07T14:32:23.142+00:00",
                "modifiedAt": "2022-07-08T03:14:37.274+00:00"
            }
        ]
        ```
        """

        params = {}
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("cdumaps")
        return self.get(f"{url}/{cdu_id}/datasets", params=params)

    def iter_datasets_in_a_cdu(self, cdu_id, limit=100):
        """
        Gets all datasets that belong to a cdu
        :param cdu_id: Crux Delivery Unit identifier (e.g., Cx20336)
        :param limit:
        :return:
        Example
        ```
        [
            {
                "id": "DsgLm9fZ",
                "legacyId": "AQKgLm9fZZpr5GM8Sti84Vd-iQ",
                "name": "us_eia_form_eia_923_data_history",
                "description": "",
                "workflowId": "us_eia_form_eia_923_data_history",
                "ownerIdentityId": "IQEY3WKncGbfXhGJN1K7KM0OWg",
                "cronSchedule": "@once",
                "publicDs": false,
                "approved": false,
                "afVar": "US_EIA_FORM_EIA_923_DATA_HISTORY_API",
                "tags": [],
                "createdAt": "2022-07-04T13:13:42.524+00:00",
                "modifiedAt": "2022-07-08T03:15:52.213+00:00"
            },
            {
                "id": "DsoMwNLi",
                "legacyId": "AQLoMwNLiQNypFRmB2dwS2Zf3g",
                "name": "us_eia_form_eia_923_data_ongoing",
                "description": "",
                "workflowId": "us_eia_form_eia_923_data_ongoing",
                "ownerIdentityId": "IQEY3WKncGbfXhGJN1K7KM0OWg",
                "cronSchedule": "0 20 25-31 * *",
                "publicDs": false,
                "approved": false,
                "afVar": "US_EIA_FORM_EIA_923_DATA_ONGOING_API",
                "tags": [],
                "createdAt": "2022-07-07T14:32:23.142+00:00",
                "modifiedAt": "2022-07-08T03:14:37.274+00:00"
            }
        ]
        ```
        """

        offset = 0
        while True:
            response = self.get_datasets_in_a_cdu(
                cdu_id=cdu_id, offset=offset, limit=limit
            )
            if not response:
                break
            yield from response
            offset += limit

    def get_dataset_ids_in_a_cdu(self, cdu_id):
        """
        Gets all dataset ids that belong to a cdu
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-maps/getV2OpsCdumapsCduidDatasetids
        :param cdu_id: Crux Delivery Unit identifier (e.g., Cx20336)
        :return:
        Example:
        ```
        [
          "Ds1Aiq04",
          "DsJQcyWi",
          "DsOOX9fP",
          "Dsr_ZCvx",
          "DsVapAtt",
          "Ds-W_IHg"
        ]
        ```
        """

        url = self.resource_url("cdumaps")
        return self.get(f"{url}/{cdu_id}/datasetIds")

    def create_cdu_map(self, data):
        """
        Creates a new cdu map
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-maps/postV2OpsCdumaps
        :param data: CDU ID <-> DATASET ID mapping information
        Example
        ```
        {
          "cduId": "Cx02320",
          "datasetId": "DsdCUZVf"
        }
        ```
        :return:
        Example
        ```
        {
          "cduId": "Cx02320",
          "createdAt": "2023-08-16T22:35:22.509+00:00",
          "datasetId": "DsdCUZVf"
        }
        ```
        """

        url = self.resource_url("cdumaps")
        return self.post(url, json=data)

    def create_bulk_cdu_maps(self, data):
        """
        Creates a list of cdu-maps
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-maps/putV2OpsCdumaps
        :param data: A list of CDU ID <-> DATASET ID mapping information
        Example
        ```
        [
          {
            "cduId": "Cx02177",
            "datasetId": "DsdCUZVf"
          },
          {
            "cduId": "Cx02320",
            "datasetId": "DsOHaREf"
          }
        ]
        ```
        :return:
        Example
        ```
        [
          {
            "cduId": "Cx02177",
            "createdAt": "2023-08-16T23:37:39.392+00:00",
            "datasetId": "DsdCUZVf"
          },
          {
            "cduId": "Cx02320",
            "createdAt": "2023-08-16T23:37:39.429+00:00",
            "datasetId": "DsOHaREf"
          }
        ]
        ```
        """

        url = self.resource_url("cdumaps")
        return self.put(url, json=data)

    def update_cdu_map(self, cdu_id, dataset_id, data):
        """
        Updates cdumap specified by its cduId and datasetId.
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-maps/putV2OpsCdumapsCduidDatasetid
        :param cdu_id: Crux Delivery Unit identifier (e.g., Cx02320)
        :param dataset_id: Dataset identifier (e.g., DsdCUZVf or AQJdCUZVflrGGDH7NqHxwQFAsQ)
        :param data: CDU ID <-> DATASET ID mapping information
        Example
        ```
        {
          "cduId": "Cx02320",
          "datasetId": "DsdCUZVf"
        }
        ```
        :return:
        """

        url = self.resource_url("cdumaps")
        return self.put(f"{url}/{cdu_id}/{dataset_id}", json=data)

    def delete_cdu_map(self, cdu_id, dataset_id):
        """
        Deletes cdumap specified by its cduId and datasetId
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-maps/deleteV2OpsCdumapsCduidDatasetid
        :param cdu_id: Crux Delivery Unit identifier (e.g., Cx02320)
        :param dataset_id: Dataset identifier (e.g., DsdCUZVf or AQJdCUZVflrGGDH7NqHxwQFAsQ)
        :return:
        """

        url = self.resource_url("cdumaps")
        return self.delete(f"{url}/{cdu_id}/{dataset_id}")

    def get_resource_metadata(self, resource_id):
        """
        Gets metadata for the specified resource.
        https://api.cruxinformatics.com/v2/ops/swagger#/resources-v2/getV2OpsResourcesResourceid
        :param resource_id: Resource identifier (e.g., EQMDs7Jj6QJ22041230065a78a)
        :return:
        Example
        ```
        {
          "resourceId": "EQMDs7Jj6QJ22041230065a78a",
          "datasetId": "AQJ7Jj6QJoD-NErSj__8LQzl9Q",
          "frameId": "ecb_asset_purchase_programs_abspp_breakdown_of_holdings_end_of_month_at_amortised_cost",
          "workflowId": "ecb_asset_purchase_programs_abspp_breakdown_of_holdings_end_of_month_at_amortised_cost",
          "pipelineId": "ecb_asset_purchase_programs_abspp_breakdown_of_holdings_end_of_month_at_amortised_cost",
          "stepId": "process",
          "ingestionId": "9cc68483b4432e08aa84336799bb104243fda20c33595aa8bea2edcc80c419c0",
          "versionId": "0",
          "vendorPath": "mopo/implement/app/html",
          "folderId": "QQMDs7Jj6QJ220412533c0c2bb",
          "mediaType": "avro/binary",
          "name": "ABSPP_breakdown_of_holdings_end_of_month_at_amortised_cost.avro",
          "type": "file",
          "size": 785,
          "uncompressedSize": null,
          "storageId": "file_6b767201f42e666df9114ae05f5dd5b2",
          "deliveryType": "delta",
          "rawResourceId": "EQMDs7Jj6QJ220412157801158",
          "pdkVersion": "2.0.4",
          "sourceDigest": "NO_FILE",
          "uncompressedMediaType": "avro/binary",
          "md5Hash": "7e385968c12e92b1858ff75224e86691",
          "supplierImpliedDt": "2022-04-12T08:00:00Z",
          "scheduleDt": "2022-04-12T16:00:00Z",
          "supplierModifiedDt": null,
          "workflowRunDt": "2022-04-12T22:10:18Z",
          "stepRunDt": "2022-04-12T22:17:53.249Z",
          "pipelineRunDt": "2022-04-12T22:10:18.693Z",
          "extractDt": "2022-04-12T22:12:55.126Z",
          "ingestionDt": "2022-04-12T22:12:56.018Z",
          "cruxAvailableDt": "2022-04-12T22:17:57.863Z",
          "createdAt": "2022-04-12T22:17:54.143Z",
          "modifiedAt": "2022-04-12T22:17:58.162Z",
          "labels": null,
          "tags": null,
          "deliveryId": "9cc68483b4432e08aa84336799bb104243fda20c33595aa8bea2edcc80c419c0.0"
        }
        ```
        """

        url = self.resource_url("resources")
        return self.get(f"{url}/{resource_id}")

    def get_resource_metadata_batch(self, resource_ids):
        """
        Get resources by "ids"
        See https://api.cruxinformatics.com/v2/ops/swagger#/resources-v2/getV2OpsResources
        :param resource_ids: (e.g., "EQMDs7Jj6QJ22041215780115", "EQMDs4Kgdnld4e86622d5d4f53")
        :return:
        """

        params = {}
        if resource_ids:
            params["ids"] = ",".join(resource_ids)
        url = self.resource_url("resources")
        return self.get(url, params=params)

    def get_resource_folder_path(self, resource_id):
        """
        Gets the folder path for the given resource
        See https://api.cruxinformatics.com/v2/ops/swagger#/resources-v2/getV2OpsResourcesResourceidFolderpath
        :param resource_id: Resource identifier (e.g., "EQMDs7Jj6QJ220412157801158")
        :return:
        Example
        ```
        {
          "path": "/data/ecb_asset__cost/root/extract/ingestion_id=9cc68483b4432e08ac80c419c0/version_id=0/origin/implement/app/html"
        }
        ```
        """

        url = self.resource_url("resources")
        return self.get(f"{url}/{resource_id}/folderpath")

    def get_dataframe_catalog(self, filter_query=None, offset=0, limit=100):
        """
        Get Dataframes (Brief) by Frame (In) id
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsDataframesByframeFrameid
        :param filter_query: (e.g., id.eq.DfDe1e5f1087ed05)
        :param offset:
        :param limit:
        :return:
        Example
        ```
        [
          {
            "id": "DfDe1e5f1087ed05",
            "type": "BASE",
            "name": "snp_xpressfeed_snl_insurance_statutory_geo_pc_fundamentals_snl_stat_pc_geo_stk_prd_num_full",
            "version": 1,
            "status": "LIVE",
            "inFrame": {
              "id": "Fr003GiV399ecc",
              "frameId": "snp_xpressfeed_snl_insurance_statutory_geo_pc_fundamentals_snl_stat_pc_geo_stk_prd_num_full",
              "frameStatus": "GENERATED",
              "workflowId": "snp_xpressfeed_snl_insurance_statutory_geo_pc_fundamentals_stk_num_full",
              "datasetId": "Ds003GiV",
              "datasetLegacyId": "AQI003GiV6d1fjKxJ6_cVP_ijA",
              "orgId": "OrXhrcjp",
              "orgCode": "SPG",
              "orgExternalId": "CXO83169"
            },
            "outFrame": {
              "id": "Fr003GiV399ecc",
              "frameId": "snp_xpressfeed_snl_insurance_statutory_geo_pc_fundamentals_snl_stat_pc_geo_stk_prd_num_full",
              "frameStatus": "GENERATED",
              "workflowId": "snp_xpressfeed_snl_insurance_statutory_geo_pc_fundamentals_stk_num_full",
              "datasetId": "Ds003GiV",
              "datasetLegacyId": "AQI003GiV6d1fjKxJ6_cVP_ijA",
              "orgId": "OrXhrcjp",
              "orgCode": "SPG",
              "orgExternalId": "CXO83169"
            }
          },
          {
            "id": "DfDea48b610097f8",
            "type": "BASE",
            "name": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
            "version": 1,
            "status": "LIVE",
            "inFrame": {
              "id": "Fr00-86xf9ec54",
              "frameId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
              "frameStatus": "GENERATED",
              "workflowId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
              "datasetId": "Ds00-86x",
              "datasetLegacyId": "AQI00-86xL8ifTemnYCTehPPhw",
              "cduId": "Cx13553",
              "cduMutualizable": "false",
              "orgId": "Orqvrs2k",
              "orgCode": "STOXX",
              "orgExternalId": "CXO07233"
            },
            "outFrame": {
              "id": "Fr00-86xf9ec54",
              "frameId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
              "frameStatus": "GENERATED",
              "workflowId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
              "datasetId": "Ds00-86x",
              "datasetLegacyId": "AQI00-86xL8ifTemnYCTehPPhw",
              "cduId": "Cx13553",
              "cduMutualizable": "false",
              "orgId": "Orqvrs2k",
              "orgCode": "STOXX",
              "orgExternalId": "CXO07233"
            }
          }
        ]
        ```
        """

        params = {}
        if filter_query:
            params["filter"] = filter_query
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("dataframe-catalog")
        return self.get(url, params=params)

    def get_dataframe_by_id(self, dataframe_id):
        """
        Get Dataframe (Full Format) by Id
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsDataframesId
        :param dataframe_id: (e.g., DfDe7ea30ef26acf)
        :return:
        Example
        ```
        {
          "id": "DfDe6afece0db917",
          "type": "BASE",
          "name": "bank_of_canada_holdings_history_total_holdings_gov_of_canada_and_canada_mortgage_bond_securities",
          "inFrameId": "FrSSLVGX96a4ac",
          "outFrameId": "FrSSLVGX96a4ac",
          "version": 1,
          "startDate": "2000-01-01",
          "endDate": "2099-01-01",
          "status": "LIVE",
          "mapping": [
            {
              "inPos": 1,
              "inId": "Fd756d967201a133af",
              "inName": "Total_holdings_of_Government_of_Canada_and_Canada_Mortgage_Bond_securities",
              "inType": "INTEGER",
              "outPos": 1,
              "outId": "Fde86432d2c8737d6c",
              "outName": "Total_holdings_of_Government_of_Canada_and_Canada_Mortgage_Bond_securities",
              "outType": "INTEGER",
              "operation": "ASIS",
              "pk": false,
              "fk": false
            },
            {
              "inPos": 2,
              "outPos": 2,
              "outId": "Fd6c61ebd4ff2e0442",
              "outName": "crux_ingestion_dt",
              "outType": "DATETIME",
              "operation": "CRUXMETA",
              "params": "crux_ingestion_dt",
              "pk": false,
              "fk": false
            },
            {
              "inPos": 3,
              "outPos": 3,
              "outId": "Fd322053b4b7285351",
              "outName": "crux_supplier_implied_dt",
              "outType": "DATETIME",
              "operation": "CRUXMETA",
              "params": "crux_supplier_implied_dt",
              "pk": false,
              "fk": false
            },
            {
              "inPos": 4,
              "outPos": 4,
              "outId": "Fd0d57eead59388f64",
              "outName": "crux_delivery_id",
              "outType": "STRING",
              "operation": "CRUXMETA",
              "params": "crux_delivery_id",
              "pk": false,
              "fk": false
            },
            {
              "inPos": 5,
              "outPos": 5,
              "outId": "Fda0005d407a6335a7",
              "outName": "crux_resource_id",
              "outType": "STRING",
              "operation": "CRUXMETA",
              "params": "crux_resource_id",
              "pk": false,
              "fk": false
            }
          ],
          "createdAt": "2023-03-29T19:17:45.788+00:00",
          "modifiedAt": "2023-03-29T19:17:45.788+00:00"
        }
        ```
        """

        url = self.resource_url("dataframes")
        return self.get(f"{url}/{dataframe_id}")

    def get_dataframes_by_frame_id(self, frame_id):
        """
        Get Dataframes (Brief) by Frame (In) id
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsDataframesByframeFrameid
        :param frame_id: (e.g., FrSSLVGX96a4ac)
        :return:
        Example
        ```
        [
          {
            "id": "DfDe6afece0db917",
            "type": "BASE",
            "name": "bank_of_canada_holdings_history_total_holdings_gov_of_canada_and_canada_mortgage_bond_securities",
            "inFrameId": "FrSSLVGX96a4ac",
            "outFrameId": "FrSSLVGX96a4ac",
            "version": 1,
            "startDate": "2000-01-01",
            "endDate": "2099-01-01",
            "status": "LIVE",
            "mapping": [
              {
                "inPos": 1,
                "inId": "Fd756d967201a133af",
                "inName": "Total_holdings_of_Government_of_Canada_and_Canada_Mortgage_Bond_securities",
                "inType": "INTEGER",
                "outPos": 1,
                "outId": "Fde86432d2c8737d6c",
                "outName": "Total_holdings_of_Government_of_Canada_and_Canada_Mortgage_Bond_securities",
                "outType": "INTEGER",
                "operation": "ASIS",
                "pk": false,
                "fk": false
              },
              {
                "inPos": 2,
                "outPos": 2,
                "outId": "Fd6c61ebd4ff2e0442",
                "outName": "crux_ingestion_dt",
                "outType": "DATETIME",
                "operation": "CRUXMETA",
                "params": "crux_ingestion_dt",
                "pk": false,
                "fk": false
              },
              {
                "inPos": 3,
                "outPos": 3,
                "outId": "Fd322053b4b7285351",
                "outName": "crux_supplier_implied_dt",
                "outType": "DATETIME",
                "operation": "CRUXMETA",
                "params": "crux_supplier_implied_dt",
                "pk": false,
                "fk": false
              },
              {
                "inPos": 4,
                "outPos": 4,
                "outId": "Fd0d57eead59388f64",
                "outName": "crux_delivery_id",
                "outType": "STRING",
                "operation": "CRUXMETA",
                "params": "crux_delivery_id",
                "pk": false,
                "fk": false
              },
              {
                "inPos": 5,
                "outPos": 5,
                "outId": "Fda0005d407a6335a7",
                "outName": "crux_resource_id",
                "outType": "STRING",
                "operation": "CRUXMETA",
                "params": "crux_resource_id",
                "pk": false,
                "fk": false
              }
            ],
            "createdAt": "2023-03-29T19:17:45.788+00:00",
            "modifiedAt": "2023-03-29T19:17:45.788+00:00"
          }
        ]
        ```
        """

        url = self.resource_url("dataframes")
        return self.get(f"{url}/by-frame/{frame_id}")

    def get_dataframe_fields(self, dataframe_id):
        """
        Get Dataframe's In and Out field definitions
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsDataframesIdFields
        :param dataframe_id: (e.g., DfDe6afece0db917)
        :return:
        Example
        ```
        [
          {
            "id": "Fd756d967201a133af",
            "orgId": "Or2zwFAS",
            "fieldName": "Total_holdings_of_Government_of_Canada_and_Canada_Mortgage_Bond_securities",
            "fieldType": "INTEGER",
            "description": "From outbound_fields",
            "preferred": false,
            "status": "DEV",
            "createdAt": "2022-04-06T08:33:42.713+00:00",
            "modifiedAt": "2022-04-06T08:33:42.713+00:00"
          },
          {
            "id": "Fde86432d2c8737d6c",
            "orgId": "Oruh6UEr",
            "fieldName": "Total_holdings_of_Government_of_Canada_and_Canada_Mortgage_Bond_securities",
            "fieldType": "INTEGER",
            "description": "Total holdings of Government of Canada and Canada Mortgage Bond securities.",
            "preferred": false,
            "status": "CURATED",
            "createdAt": "2022-04-06T08:35:27.012+00:00",
            "modifiedAt": "2022-04-06T08:35:27.012+00:00"
          },
          {
            "id": "Fd6c61ebd4ff2e0442",
            "orgId": "Oruh6UEr",
            "fieldName": "crux_ingestion_dt",
            "fieldType": "DATETIME",
            "description": "UTC Datetime a delivery was processed",
            "crossRef": "DATETIME",
            "preferred": true,
            "status": "CURATED",
            "createdAt": "2021-05-04T20:57:28.536+00:00",
            "modifiedAt": "2021-05-04T20:57:28.536+00:00"
          },
          {
            "id": "Fd322053b4b7285351",
            "orgId": "Oruh6UEr",
            "fieldName": "crux_supplier_implied_dt",
            "fieldType": "DATETIME",
            "description": "UTC Datetime of the data within a frame from Suppliers perspective ",
            "crossRef": "DATETIME",
            "preferred": true,
            "status": "CURATED",
            "createdAt": "2021-05-04T20:57:28.574+00:00",
            "modifiedAt": "2021-05-04T20:57:28.574+00:00"
          },
          {
            "id": "Fd0d57eead59388f64",
            "orgId": "Oruh6UEr",
            "fieldName": "crux_delivery_id",
            "fieldType": "STRING",
            "description": "Unique Identifier for 1 or more files processed together",
            "crossRef": "IDENTIFIER",
            "preferred": true,
            "status": "CURATED",
            "createdAt": "2021-05-04T20:57:28.609+00:00",
            "modifiedAt": "2021-05-04T20:57:28.609+00:00"
          },
          {
            "id": "Fda0005d407a6335a7",
            "orgId": "Oruh6UEr",
            "fieldName": "crux_resource_id",
            "fieldType": "STRING",
            "description": "Unique identifier for the underlying physical resource of the dataset",
            "crossRef": "IDENTIFIER",
            "preferred": true,
            "status": "CURATED",
            "createdAt": "2021-05-04T20:57:28.644+00:00",
            "modifiedAt": "2021-05-04T20:57:28.644+00:00"
          }
        ]
        ```
        """

        url = self.resource_url("dataframes")
        return self.get(f"{url}/{dataframe_id}/fields")

    def get_dataframe_fields_in(self, dataframe_id):
        """
        Get Dataframe's In field definitions
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsDataframesIdFieldsIn
        :param dataframe_id: (e.g., DfDe6afece0db917)
        :return:
        Example
        ```
        [
          {
            "id": "Fd756d967201a133af",
            "orgId": "Or2zwFAS",
            "fieldName": "Total_holdings_of_Government_of_Canada_and_Canada_Mortgage_Bond_securities",
            "fieldType": "INTEGER",
            "description": "From outbound_fields",
            "preferred": false,
            "status": "DEV",
            "createdAt": "2022-04-06T08:33:42.713+00:00",
            "modifiedAt": "2022-04-06T08:33:42.713+00:00"
          }
        ]
        ```
        """

        url = self.resource_url("dataframes")
        return self.get(f"{url}/{dataframe_id}/fields/in")

    def get_dataframe_fields_out(self, dataframe_id):
        """
        Get Dataframe's Out field definitions
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsDataframesIdFieldsOut
        :param dataframe_id: (e.g., DfDe6afece0db917)
        :return:
        Example
        ```
        [
          {
            "id": "Fde86432d2c8737d6c",
            "orgId": "Oruh6UEr",
            "fieldName": "Total_holdings_of_Government_of_Canada_and_Canada_Mortgage_Bond_securities",
            "fieldType": "INTEGER",
            "description": "Total holdings of Government of Canada and Canada Mortgage Bond securities.",
            "preferred": false,
            "status": "CURATED",
            "createdAt": "2022-04-06T08:35:27.012+00:00",
            "modifiedAt": "2022-04-06T08:35:27.012+00:00"
          },
          {
            "id": "Fd6c61ebd4ff2e0442",
            "orgId": "Oruh6UEr",
            "fieldName": "crux_ingestion_dt",
            "fieldType": "DATETIME",
            "description": "UTC Datetime a delivery was processed",
            "crossRef": "DATETIME",
            "preferred": true,
            "status": "CURATED",
            "createdAt": "2021-05-04T20:57:28.536+00:00",
            "modifiedAt": "2021-05-04T20:57:28.536+00:00"
          },
          {
            "id": "Fd322053b4b7285351",
            "orgId": "Oruh6UEr",
            "fieldName": "crux_supplier_implied_dt",
            "fieldType": "DATETIME",
            "description": "UTC Datetime of the data within a frame from Suppliers perspective ",
            "crossRef": "DATETIME",
            "preferred": true,
            "status": "CURATED",
            "createdAt": "2021-05-04T20:57:28.574+00:00",
            "modifiedAt": "2021-05-04T20:57:28.574+00:00"
          },
          {
            "id": "Fd0d57eead59388f64",
            "orgId": "Oruh6UEr",
            "fieldName": "crux_delivery_id",
            "fieldType": "STRING",
            "description": "Unique Identifier for 1 or more files processed together",
            "crossRef": "IDENTIFIER",
            "preferred": true,
            "status": "CURATED",
            "createdAt": "2021-05-04T20:57:28.609+00:00",
            "modifiedAt": "2021-05-04T20:57:28.609+00:00"
          },
          {
            "id": "Fda0005d407a6335a7",
            "orgId": "Oruh6UEr",
            "fieldName": "crux_resource_id",
            "fieldType": "STRING",
            "description": "Unique identifier for the underlying physical resource of the dataset",
            "crossRef": "IDENTIFIER",
            "preferred": true,
            "status": "CURATED",
            "createdAt": "2021-05-04T20:57:28.644+00:00",
            "modifiedAt": "2021-05-04T20:57:28.644+00:00"
          }
        ]
        ```
        """

        url = self.resource_url("dataframes")
        return self.get(f"{url}/{dataframe_id}/fields/out")

    def get_dataframe_fields_out_crux(self, dataframe_id):
        """
        Get Dataframe's Out field definitions in Crux format
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsDataframesIdFieldsOutCrux
        :param dataframe_id: (e.g., DfDe6afece0db917)
        :return:
        Example
        ```
        {
          "fields": [
            {
              "name": "Total_holdings_of_Government_of_Canada_and_Canada_Mortgage_Bond_securities",
              "dataType": "INTEGER"
            }
          ]
        }
        ```
        """

        url = self.resource_url("dataframes")
        return self.get(f"{url}/{dataframe_id}/fields/out/crux")

    def get_dataframe_status(self, dataframe_id):
        """
        Return current Onboarding status
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsDataframesIdStatus
        :param dataframe_id: (e.g., DfDe6afece0db917)
        :return:
        Example: `GENERATED`, `CONFIGURED`, `DOCUMENTED`, `PROTECTED`, `CURATED`
                 `LIVE`, `ENRICHED`, `RELEASED`, `DEV`
        """

        url = self.resource_url("dataframes")
        return self.get(f"{url}/{dataframe_id}/status", raw_response=True).text

    def get_dataframes_by_cdu_and_type(
        self, cdu_id, df_type, offset=0, limit=1000, after="Df"
    ):
        """
        Get Dataframes (Brief) by CDU id and Dataframe type
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsDataframesBycduCduidTypeType
        :param cdu_id: Crux Delivery Unit identifier (e.g., Cx49736)
        :param df_type:
        :param offset:
        :param limit:
        :param after:
        :return:
        Example
        ```
        [
          {
            "id": "DfDe573811968486",
            "type": "WRANGLE",
            "name": "morningstar_rating_available_for_sale__active_most_recent_full_load",
            "inFrameId": "FrGJqZgy5c3890",
            "outFrameId": "FrGJqZgy5c3890",
            "version": 1,
            "status": "LIVE"
          }
        ]
        ```
        """

        params = {}
        if after:
            params["after"] = after
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("dataframes")
        return self.get(f"{url}/by-cdu/{cdu_id}/type/{df_type}", params=params)

    def get_frame_catalogs(self, filter_query=None, offset=0, limit=100):
        """
        Get catalog entries with optional [offset, limit] and [filter] parameters
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsFramecatalog
        :param filter_query: (e.g., frameStatus.eq.GENERATED)
        :param offset:
        :param limit:
        :return:
        Example
        ```
        [
          {
            "id": "FrSExyAKda3dfd",
            "frameId": "Wrangle_ESG_RATINGS_COVERED",
            "frameStatus": "GENERATED",
            "workflowId": "Wrangle_ESG_RATINGS_COVERED",
            "datasetId": "DsSExyAK",
            "datasetLegacyId": "AQKSExyAK5vb2RQZHQYEONi8Kw",
            "cduId": "Cx22497",
            "cduMutualizable": "true",
            "orgId": "OrqaTq5O",
            "orgCode": "MSCI",
            "orgExternalId": "CXO31190"
          },
          {
            "id": "FrH2AU469fc0e4",
            "frameId": "nasdaq_93eedfa1_evest_view_csv_v5",
            "frameStatus": "DEV",
            "workflowId": "nasdaq_93eedfa1_evest_view_v5",
            "datasetId": "DsH2AU46",
            "datasetLegacyId": "AQKH2AU46hbNyKwVQwtFVcFh9Q",
            "orgId": "OrgaUXIQ",
            "orgCode": "NASDAQ",
            "orgExternalId": "CXO35936"
          },
        ]
        ```
        """

        params = {}
        if filter_query:
            params["filter"] = filter_query
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("frame-catalog")
        return self.get(url, params=params)

    def iter_frame_catalogs_all(self, filter_query=None, limit=100):
        """
        Get catalog entries with optional [offset, limit] and [filter] parameters
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsFramecatalog
        :param filter_query: (e.g., frameStatus.eq.GENERATED)
        :param limit:
        :return:
        """

        offset = 0
        while True:
            response = self.get_frame_catalogs(
                filter_query=filter_query, offset=offset, limit=limit
            )
            if not response:
                break
            yield from response
            offset += limit

    def get_frame_catalog_by_cdu_id(self, cdu_id, after="Fr", offset=0, limit=100):
        """
        Get catalog entries by CDU id
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsFramecatalogBycduCduid
        :param cdu_id: Crux Delivery Unit identifier (e.g., Cx13553)
        :param after:
        :param offset:
        :param limit:
        :return:
        Example
        ```
        [
          {
            "id": "Fr00-86xf9ec54",
            "frameId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
            "frameStatus": "GENERATED",
            "workflowId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
            "datasetId": "Ds00-86x",
            "datasetLegacyId": "AQI00-86xL8ifTemnYCTehPPhw",
            "cduId": "Cx13553",
            "cduMutualizable": "false",
            "orgId": "Orqvrs2k",
            "orgCode": "STOXX",
            "orgExternalId": "CXO07233"
          },
          {
            "id": "Fr03c7M600b62d",
            "frameId": "stoxx_sector_sxp175gv_historical_files_h_txt_s4",
            "frameStatus": "GENERATED",
            "workflowId": "stoxx_sector_sxp175gv_historical_files_daily",
            "datasetId": "Ds03c7M6",
            "datasetLegacyId": "AQL03c7M6pULtcJhfmvUOzUE2Q",
            "cduId": "Cx13553",
            "cduMutualizable": "false",
            "orgId": "Orqvrs2k",
            "orgCode": "STOXX",
            "orgExternalId": "CXO07233"
          },
        ]
        ```
        """

        params = {}
        if after:
            params["after"] = after
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("frame-catalog")
        return self.get(f"{url}/by-cdu/{cdu_id}", params=params)

    def get_frame_catalog_by_dataset_id(self, dataset_id):
        """
        Get catalog entries by dataset id
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsFramecatalogBydatasetDatasetid
        :param dataset_id: Dataset identifier (e.g., Ds03c7M6 or AQL03c7M6pULtcJhfmvUOzUE2Q)
        :return:
        Example
        ```
        [
          {
            "id": "Fr00-86xf9ec54",
            "frameId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
            "frameStatus": "GENERATED",
            "workflowId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
            "datasetId": "Ds00-86x",
            "datasetLegacyId": "AQI00-86xL8ifTemnYCTehPPhw",
            "cduId": "Cx13553",
            "cduMutualizable": "false",
            "orgId": "Orqvrs2k",
            "orgCode": "STOXX",
            "orgExternalId": "CXO07233"
          },
          {
            "id": "Fr03c7M600b62d",
            "frameId": "stoxx_sector_sxp175gv_historical_files_h_txt_s4",
            "frameStatus": "GENERATED",
            "workflowId": "stoxx_sector_sxp175gv_historical_files_daily",
            "datasetId": "Ds03c7M6",
            "datasetLegacyId": "AQL03c7M6pULtcJhfmvUOzUE2Q",
            "cduId": "Cx13553",
            "cduMutualizable": "false",
            "orgId": "Orqvrs2k",
            "orgCode": "STOXX",
            "orgExternalId": "CXO07233"
          },
        ]
        ```
        """

        url = self.resource_url("frame-catalog")
        return self.get(f"{url}/by-dataset/{dataset_id}")

    def get_frame_catalog_by_frame_name(self, frame_name):
        """
        Get catalog entries by frame name (aka frame_id)
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsFramecatalogByframenameName
        :param frame_name: (e.g., stoxx_sector_sx6gt_review_files_qr_sx6e_csv)
        :return:
        Example
        ```
        [
          {
            "id": "FrqY4YoJf9ec54",
            "frameId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
            "frameStatus": "GENERATED",
            "workflowId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
            "datasetId": "DsqY4YoJ",
            "datasetLegacyId": "AQKqY4YoJUxf6-MGsJJ7ZNTOpA",
            "orgId": "Orqvrs2k",
            "orgCode": "STOXX",
            "orgExternalId": "CXO07233"
          },
          {
            "id": "Fr00-86xf9ec54",
            "frameId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
            "frameStatus": "GENERATED",
            "workflowId": "stoxx_sector_sx6gt_review_files_qr_sx6e_csv",
            "datasetId": "Ds00-86x",
            "datasetLegacyId": "AQI00-86xL8ifTemnYCTehPPhw",
            "cduId": "Cx13553",
            "cduMutualizable": "false",
            "orgId": "Orqvrs2k",
            "orgCode": "STOXX",
            "orgExternalId": "CXO07233"
          }
        ]
        ```
        """

        url = self.resource_url("frame-catalog")
        return self.get(f"{url}/by-frame-name/{frame_name}")

    def get_frame_catalog_by_frame_id(self, frame_id):
        """
        Get catalog entry by id of the frame (primary key)
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsFramecatalogByframeFrameid
        :param frame_id: (e.g., FrwMvzNv732539)
        :return:
        Example
        ```
        {
          "id": "FrwMvzNv732539",
          "frameId": "boardex_director_standard_remuneration_ongoing",
          "frameStatus": "GENERATED",
          "workflowId": "boardex_standard_remuneration_4_1_ongoing",
          "datasetId": "DswMvzNv",
          "datasetLegacyId": "AQLwMvzNv_q9v21sEGqwMX40Sw",
          "cduId": "Cx15175",
          "cduMutualizable": "true",
          "orgId": "OrasC0lJ",
          "orgCode": "BOARDEX",
          "orgExternalId": "CXO64185"
        }
        ```
        """

        url = self.resource_url("frame-catalog")
        return self.get(f"{url}/by-frame/{frame_id}")

    def get_frame_catalog_by_vendor_org_id(
        self, org_id, after="Fr", offset=0, limit=100
    ):
        """
        Get catalog entries by vendor's org id
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsFramecatalogByvendoridOrgid
        :param org_id: Organization identifier (e.g., OrHgHOd2)
        :param after:
        :param offset:
        :param limit:
        :return:
        Example
        ```
        [
          {
            "id": "Frv9zMdN599494",
            "frameId": "above_data_user_experience_and_education_data_cxo71191_position",
            "frameStatus": "GENERATED",
            "workflowId": "above_data_user_experience_and_education_data_cxo71191",
            "datasetId": "Dsv9zMdN",
            "datasetLegacyId": "AQJv9zMdNSuZLaXL0wlyhN5NZQ",
            "cduId": "Cx30508",
            "cduMutualizable": "false",
            "orgId": "OrHgHOd2",
            "orgCode": "ABOVEDATA",
            "orgExternalId": "CXO13788"
          },
          {
            "id": "Frv9zMdN9115ce",
            "frameId": "above_data_user_experience_and_education_data_cxo71191_user",
            "frameStatus": "GENERATED",
            "workflowId": "above_data_user_experience_and_education_data_cxo71191",
            "datasetId": "Dsv9zMdN",
            "datasetLegacyId": "AQJv9zMdNSuZLaXL0wlyhN5NZQ",
            "cduId": "Cx30508",
            "cduMutualizable": "false",
            "orgId": "OrHgHOd2",
            "orgCode": "ABOVEDATA",
            "orgExternalId": "CXO13788"
          },
          {
            "id": "Frv9zMdNc98332",
            "frameId": "above_data_user_experience_and_education_data_cxo71191_education",
            "frameStatus": "GENERATED",
            "workflowId": "above_data_user_experience_and_education_data_cxo71191",
            "datasetId": "Dsv9zMdN",
            "datasetLegacyId": "AQJv9zMdNSuZLaXL0wlyhN5NZQ",
            "cduId": "Cx30508",
            "cduMutualizable": "false",
            "orgId": "OrHgHOd2",
            "orgCode": "ABOVEDATA",
            "orgExternalId": "CXO13788"
          }
        ]
        ```
        """

        params = {}
        if after:
            params["after"] = after
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("frame-catalog")
        return self.get(f"{url}/by-vendor-id/{org_id}", params=params)

    def get_frame_catalog_by_vendor_org_code(
        self, org_code, after="Fr", offset=0, limit=100
    ):
        """
        Get catalog entries by vendor's org code
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsFramecatalogByvendorcodeOrgcode
        :param org_code: (e.g., ABOVEDATA)
        :param after:
        :param offset:
        :param limit:
        :return:
        Example
        ```
        [
          {
            "id": "Frv9zMdN599494",
            "frameId": "above_data_user_experience_and_education_data_cxo71191_position",
            "frameStatus": "GENERATED",
            "workflowId": "above_data_user_experience_and_education_data_cxo71191",
            "datasetId": "Dsv9zMdN",
            "datasetLegacyId": "AQJv9zMdNSuZLaXL0wlyhN5NZQ",
            "cduId": "Cx30508",
            "cduMutualizable": "false",
            "orgId": "OrHgHOd2",
            "orgCode": "ABOVEDATA",
            "orgExternalId": "CXO13788"
          },
          {
            "id": "Frv9zMdN9115ce",
            "frameId": "above_data_user_experience_and_education_data_cxo71191_user",
            "frameStatus": "GENERATED",
            "workflowId": "above_data_user_experience_and_education_data_cxo71191",
            "datasetId": "Dsv9zMdN",
            "datasetLegacyId": "AQJv9zMdNSuZLaXL0wlyhN5NZQ",
            "cduId": "Cx30508",
            "cduMutualizable": "false",
            "orgId": "OrHgHOd2",
            "orgCode": "ABOVEDATA",
            "orgExternalId": "CXO13788"
          },
          {
            "id": "Frv9zMdNc98332",
            "frameId": "above_data_user_experience_and_education_data_cxo71191_education",
            "frameStatus": "GENERATED",
            "workflowId": "above_data_user_experience_and_education_data_cxo71191",
            "datasetId": "Dsv9zMdN",
            "datasetLegacyId": "AQJv9zMdNSuZLaXL0wlyhN5NZQ",
            "cduId": "Cx30508",
            "cduMutualizable": "false",
            "orgId": "OrHgHOd2",
            "orgCode": "ABOVEDATA",
            "orgExternalId": "CXO13788"
          }
        ]
        ```
        """

        params = {}
        if after:
            params["after"] = after
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("frame-catalog")
        return self.get(f"{url}/by-vendor-code/{org_code}", params=params)

    def get_frame_catalog_by_workflow_id(self, workflow_id):
        """
        Get catalog entries by workflow id
        See https://api.cruxinformatics.com/v2/ops/swagger#/schema/getV2OpsFramecatalogByworkflowWorkflowid
        :param workflow_id: (e.g., abc_data_residential_real_estate_trial_data)
        :return:
        Example
        ```
        [
          {
            "id": "FrVpoqNea09415",
            "frameId": "abc_data_residential_real_estate_trial_data",
            "frameStatus": "GENERATED",
            "workflowId": "abc_data_residential_real_estate_trial_data",
            "datasetId": "DsVpoqNe",
            "datasetLegacyId": "AQJVpoqNejaMGjz-IEMzczmhkg",
            "cduId": "Cx15179",
            "cduMutualizable": "true",
            "orgId": "Or0zqRDK",
            "orgCode": "ABCDATA",
            "orgExternalId": "CXO14918"
          }
        ]
        ```
        """

        url = self.resource_url("frame-catalog")
        return self.get(f"{url}/by-workflow/{workflow_id}")

    def get_cdu_subscriptions(
        self, filter_query=None, order=None, offset=0, limit=1000
    ):
        """
        Gets a list of cdu subscriptions
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-subscriptions/getV2OpsCdusubscriptions
        :param filter_query:
        :param order:
        :param offset:
        :param limit:
        :return:
        """

        params = {}
        if filter_query:
            params["filter"] = filter_query
        if order:
            params["order"] = order
        if offset is not None:
            params["offset"] = offset
        if limit:
            params["limit"] = limit
        url = self.resource_url("cduSubscriptions")
        return self.get(url, params=params)

    def iter_cdu_subscriptions_all(self, filter_query=None, order="cduId", limit=1000):
        """
        Gets a list of cdu subscriptions
        See https://api.cruxinformatics.com/v2/ops/swagger#/cdu-subscriptions/getV2OpsCdusubscriptions
        :param filter_query:
        :param order:
        :param limit:
        :return:
        """

        offset = 0
        while True:
            response = self.get_cdu_subscriptions(
                filter_query=filter_query, order=order, offset=offset, limit=limit
            )
            if not response:
                break
            yield from response
            offset += limit
