from .base import BaseModel
from .enums import DisplayColumnType, AddableColumnType, ValueType, ColumnFolderNodeType, LiveReportViewMode, \
    LiveReportResultVersionState, ReportLevel, EntityType, CellAggregationType, EntityAliasAvailability
from .models import ColumnGroup, Property


class AboutInfo(BaseModel):
    """
    Basic information about the LiveDesign server.

    :type java_version: :class:`str`
    :param java_version: The java version running on the server.

    :type java_vendor: :class:`str`
    :param java_vendor: The java vendor on the server.

    :type jchem_version: :class:`str`
    :param jchem_version: The JChem version running on the server.

    :type seurat_job_name: :class:`str`
    :param seurat_job_name: The LiveDesign job name.

    :type seurat_build_number: :class:`str`
    :param seurat_build_number: The LiveDesign build number.

    :type seurat_version_number: :class:`str`
    :param seurat_version_number: The LiveDesign version number.

    :type seurat_revision_number: :class:`str`
    :param seurat_revision_number: The LiveDesign revision number (i.e. git commit hash).

    :type seurat_license_days_remaining: :class:`int`
    :param seurat_license_days_remaining: The number of days remaining until the LiveDesign license expires.
    """
    _fields = [
        'java_version', 'java_vendor', 'jchem_version', 'livedesign_job_name',
        'livedesign_build_number', 'livedesign_release_candidate_git_branch',
        'livedesign_git_revision_number', 'livedesign_license_days_remaining'
    ]

    def __init__(self,
                 java_version=None,
                 java_vendor=None,
                 jchem_version=None,
                 livedesign_job_name=None,
                 livedesign_build_number=None,
                 livedesign_release_candidate_git_branch=None,
                 livedesign_git_revision_number=None,
                 livedesign_license_days_remaining=None):
        self.java_version = java_version
        self.java_vendor = java_vendor
        self.jchem_version = jchem_version
        self.livedesign_job_name = livedesign_job_name
        self.livedesign_build_number = livedesign_build_number
        self.livedesign_release_candidate_git_branch = livedesign_release_candidate_git_branch
        self.livedesign_git_revision_number = livedesign_git_revision_number
        self.livedesign_license_days_remaining = livedesign_license_days_remaining

    @property
    def seurat_job_name(self):
        return self.livedesign_job_name

    @seurat_job_name.setter
    def seurat_job_name(self, value):
        self.livedesign_job_name = value

    @property
    def seurat_build_number(self):
        return self.livedesign_build_number

    @seurat_build_number.setter
    def seurat_build_number(self, value):
        self.livedesign_build_number = value

    @property
    def seurat_version_number(self):
        return self.livedesign_release_candidate_git_branch

    @seurat_version_number.setter
    def seurat_version_number(self, value):
        self.livedesign_release_candidate_git_branch = value

    @property
    def seurat_revision_number(self):
        return self.livedesign_git_revision_number

    @seurat_revision_number.setter
    def seurat_revision_number(self, value):
        self.livedesign_git_revision_number = value

    @property
    def seurat_license_days_remaining(self):
        return self.livedesign_license_days_remaining

    @seurat_license_days_remaining.setter
    def seurat_license_days_remaining(self, value):
        self.livedesign_license_days_remaining = value


class MethodTimingStats(BaseModel):
    """
    Represents timing stats for a method on the server.

    :type name: :class:`str`
    :param name: The name of the method timed.

    :type mean: :class:`float`
    :param mean: The mean timing.

    :type median: :class:`int`
    :param median: The median timing.

    :type occurrences: :class:`int`
    :param occurrences: The number of occurrences of the method.

    :type max: :class:`int`
    :param max: The maximum timing.

    :type min: :class:`int`
    :param min: The minimum timing.

    :type maxTimestamp: :class:`str`
    :param maxTimestamp: The timestamp of the maximum timing.
    """
    _fields = [
        'name', 'mean', 'median', 'occurrences', 'max', 'min', 'maxTimestamp'
    ]

    def __init__(self,
                 name=None,
                 mean=None,
                 median=None,
                 occurrences=None,
                 max=None,
                 min=None,
                 maxTimestamp=None):
        self.name = name
        self.mean = mean
        self.median = median
        self.occurrences = occurrences
        self.max = max
        self.min = min
        self.maxTimestamp = maxTimestamp


class ColumnFolderNode(BaseModel):
    """
    Represents a column folder node in the column tree. This could be either a column or a folder.

    :type id: :class:`str`
    :param id: Unique identifier of the column folder node.

    :type parent_id: :class:`str`
    :param parent_id: If a subfolder or column, the ID of the parent node.

    :type name: :class:`str`
    :param name: The display name of the folder or column.

    :type original_name: :class:`str`
    :param original_name: The original name of the folder or column.

    :type children: :class:`list` of :class:`ColumnFolderNode`
    :param children: List of subfolders/columns.

    :type addable_column_ids: :class:`list` of :class:`str`
    :param addable_column_ids: List of addable column IDs if the node is a column.

    :type column_folder_node_type: :class:`~ldclient.enums.ColumnFolderNodeType`
    :param column_folder_node_type: The type of node.

    :type updated_at: :class:`int`
    :param updated_at: The last time the node was updated.

    :type addable_column_type: :class:`~ldclient.enums.AddableColumnType`
    :param addable_column_type: The type of addable column, if applicable.

    :type value_type: :class:`~ldclient.enums.ValueType`
    :param value_type: The type of value in the column, if applicable.

    :type display_column_type: :class:`~ldclient.enums.DisplayColumnType`
    :param display_column_type: The display column type, if applicable.

    :type tooltip: :class:`ColumnFolderTooltip`
    :param tooltip: Tooltip for the node.

    :type favorite_id: :class:`str`
    :param favorite_id: Favorite ID, if favorited.

    :type parameterizable_model: :class:`bool`
    :param parameterizable_model: Whether or not the node is a parameterizable model.

    :type show_create_button: :class:`bool`
    :param show_create_button: Whether or not to display the create button.

    :type model_id: :class:`str`
    :param model_id: The model ID corresponding to the node, if applicable.

    :type creator: :class:`str`
    :param creator: The creator of the node, if applicable.
    """
    _fields = [
        'id', 'parent_id', 'name', 'original_name', 'children',
        'addable_column_ids', 'column_folder_node_type', 'updated_at',
        'addable_column_type', 'value_type', 'display_column_type', 'tooltip',
        'favorite_id', 'parameterizable_model', 'show_create_button',
        'model_id', 'creator'
    ]

    def __init__(self,
                 id=None,
                 parent_id=None,
                 name=None,
                 original_name=None,
                 children=None,
                 addable_column_ids=None,
                 column_folder_node_type=None,
                 updated_at=None,
                 addable_column_type=None,
                 value_type=None,
                 display_column_type=None,
                 tooltip=None,
                 favorite_id=None,
                 parameterizable_model=None,
                 show_create_button=None,
                 model_id=None,
                 creator=None):
        self.id = id
        self.parent_id = parent_id
        self.name = name
        self.original_name = original_name
        self.children = children
        self.addable_column_ids = addable_column_ids
        self.column_folder_node_type = column_folder_node_type
        self.updated_at = updated_at
        self.addable_column_type = addable_column_type
        self.value_type = value_type
        self.display_column_type = display_column_type
        self.tooltip = tooltip
        self.favorite_id = favorite_id
        self.parameterizable_model = parameterizable_model
        self.show_create_button = show_create_button
        self.model_id = model_id
        self.creator = creator

    def serialize_children(self):
        return ColumnFolderNode.as_list(self.children)

    @staticmethod
    def deserialize_children(children):
        return ColumnFolderNode.from_list(children)

    def serialize_tooltip(self):
        return self.tooltip.as_dict()

    @staticmethod
    def deserialize_tooltip(tooltip):
        return ColumnFolderTooltip.from_dict(tooltip)

    @staticmethod
    def deserialize_column_folder_node_type(column_folder_node_type):
        return ColumnFolderNodeType.from_str(column_folder_node_type)

    @staticmethod
    def deserialize_addable_column_type(addable_column_type):
        return AddableColumnType.from_str(addable_column_type)

    @staticmethod
    def deserialize_value_type(value_type):
        return ValueType.from_str(value_type)

    @staticmethod
    def deserialize_display_column_type(display_column_type):
        return DisplayColumnType.from_str(display_column_type)


class ColumnFolderTooltip(BaseModel):
    """
    Represents a tooltip for a :class:`ColumnFolderNode`.

    :type modified_date: :class:`str`
    :param modified_date: The last date the node was modified.

    :type modified_user: :class:`str`
    :param modified_user: The last user to modify the node.

    :type description: :class:`str`
    :param description: Description displayed in the tooltip.
    """
    _fields = ['modified_date', 'modified_user', 'description']

    def __init__(self,
                 modified_date=None,
                 modified_user=None,
                 description=None):
        self.modified_date = modified_date
        self.modified_user = modified_user
        self.description = description


class LiveReportResultsMetadata(BaseModel):
    """
    Represents metadata from LiveReport results.

    :type fulfills_promise_id: :class:`int`
    :param fulfills_promise_id: The promise ID fulfilled.

    :type pending_promise_ids: :class:`list` of :class:`int`
    :param pending_promise_ids: Pending promise IDs.

    :type version: :class:`int`
    :param version: The (major) version of the results.

    :type minor_version: :class:`int`
    :param minor_version: The minor version of the results.

    :type report_level: :class:`~ldclient.enums.ReportLevel`
    :param report_level: The report level.

    :type experiment_addable_column_id: :class:`str`
    :param experiment_addable_column_id: The experiment addable column ID, if applicable.

    :type row_infos_hash: :class:`str`
    :param row_infos_hash: The hash of row informations for the results.

    :type column_infos_hash: :class:`str`
    :param column_infos_hash: The hash of column informations for the results.

    :type row_infos: :class:`list` of :class:`RowInfo`
    :param row_infos: List of metadata on each row for the results.

    :type columns: :class:`dict` of :class:`str` to :class:`ColumnDetails`
    :param columns: Dict mapping each column's ID to its metadata.

    :type column_groups: :class:`dict` of :class:`~ldclient.enums.LiveReportViewMode` to :class:`list` of
                         :class:`~ldclient.models.ColumnGroup`
    :param column_groups: For each view mode, the ordered list of column groups in the LiveReport.

    :type stats: :class:`Stats`
    :param stats: Statistics on the LiveReport.

    :type state: :class:`~ldclient.enums.LiveReportResultVersionState`
    :param state: The state of the LiveReport results (i.e. errored).

    :type message: :class:`str`
    :param message: Message, if applicable.

    :type live_report_id: :class:`str`
    :param live_report_id: The LiveReport ID that the results are on.
    """
    _fields = [
        'fulfills_promise_id', 'pending_promise_ids', 'version',
        'minor_version', 'report_level', 'experiment_addable_column_id',
        'row_infos_hash', 'column_infos_hash', 'row_infos', 'columns',
        'column_groups', 'stats', 'state', 'message', 'live_report_id'
    ]

    def __init__(self,
                 fulfills_promise_id=None,
                 pending_promise_ids=None,
                 version=None,
                 minor_version=None,
                 report_level=None,
                 experiment_addable_column_id=None,
                 row_infos_hash=None,
                 column_infos_hash=None,
                 row_infos=None,
                 columns=None,
                 column_groups=None,
                 stats=None,
                 state=None,
                 message=None,
                 live_report_id=None):
        self.fulfills_promise_id = fulfills_promise_id
        self.pending_promise_ids = pending_promise_ids
        self.version = version
        self.minor_version = minor_version
        self.report_level = report_level
        self.experiment_addable_column_id = experiment_addable_column_id
        self.row_infos_hash = row_infos_hash
        self.column_infos_hash = column_infos_hash
        self.row_infos = row_infos
        self.columns = columns
        self.column_groups = column_groups
        self.stats = stats
        self.state = state
        self.message = message
        self.live_report_id = live_report_id

    def serialize_stats(self):
        return self.stats.as_dict()

    @staticmethod
    def deserialize_stats(stats):
        return Stats.from_dict(stats)

    def serialize_row_infos(self):
        return RowInfo.as_list(self.row_infos)

    @staticmethod
    def deserialize_row_infos(row_infos):
        return RowInfo.from_list(row_infos)

    def serialize_columns(self):
        return {k: v.as_dict() for k, v in self.columns.items()}

    @staticmethod
    def deserialize_columns(columns):
        return {k: ColumnDetails.from_dict(v) for k, v in columns.items()}

    def serialize_column_groups(self):
        return {
            k.value: ColumnGroup.as_list(v)
            for k, v in self.column_groups.items()
        }

    @staticmethod
    def deserialize_column_groups(column_groups):
        return {
            LiveReportViewMode.from_str(k): ColumnGroup.from_list(v)
            for k, v in column_groups.items()
        }

    @staticmethod
    def deserialize_report_level(report_level):
        return ReportLevel.from_str(report_level)

    @staticmethod
    def deserialize_state(state):
        return LiveReportResultVersionState.from_str(state)


class RowInfo(BaseModel):
    """
    Represents a row in a LiveReport along with its metadata.

    :type row_key: :class:`str`
    :param row_key: an unique key for the row that accounts for the different livereport modes(row-per-x modes)

    :type pose_ids: :class:`list` of :class:`str`
    :param pose_ids: list of pose ids when in row-per-pose mode

    :type salt_ids: :class:`list` of :class:`str`
    :param salt_ids: list of salt ids when in row-per-salt or row-per-lot-salt mode

    :type lot_ids: :class:`list` of :class:`str`
    :param lot_ids: list of lot ids when in row-per-lot or row-per-lot-salt mode

    :type entity_id: :class:`str`
    :param entity_id: entity id for the row

    :type virtual_entity_id: :class:`str`
    :param virtual_entity_id: entity id of the linked virtual compound when this row reference a real compound

    :type display_id: :class:`str`
    :param display_id: display id for the row

    :type structure_hash: :class:`str`
    :param structure_hash: compound structure hash

    :type frozen: :class:`bool`
    :param frozen: whether or not row is frozen

    :type experiment_id: :class:`str`
    :param experiment_id: id of the experiment when in row-per-experiment mode

    :type explicitly_linked: :class:`bool`
    :param explicitly_linked: whether the real compound represented by this row has been explicitly linked to a virtual
                              compound that does not share the same canonical structure

    :type entity_type: :class:`~ldclient.enums.EntityType`
    :param entity_type: type of the entity

    :type generic_entity_file_type: :class:`str`
    :param generic_entity_file_type: file type associated to the generic entity represented by this row, if any
    """
    _fields = [
        'row_key', 'pose_ids', 'salt_ids', 'lot_ids', 'entity_id',
        'virtual_entity_id', 'display_id', 'structure_hash', 'frozen',
        'experiment_id', 'explicitly_linked', 'entity_type',
        'generic_entity_file_type'
    ]

    def __init__(self,
                 row_key=None,
                 pose_ids=None,
                 salt_ids=None,
                 lot_ids=None,
                 entity_id=None,
                 virtual_entity_id=None,
                 display_id=None,
                 structure_hash=None,
                 frozen=None,
                 experiment_id=None,
                 explicitly_linked=None,
                 entity_type=None,
                 generic_entity_file_type=None):
        self.row_key = row_key
        self.pose_ids = pose_ids
        self.salt_ids = salt_ids
        self.lot_ids = lot_ids
        self.entity_id = entity_id
        self.virtual_entity_id = virtual_entity_id
        self.display_id = display_id
        self.structure_hash = structure_hash
        self.frozen = frozen
        self.experiment_id = experiment_id
        self.explicitly_linked = explicitly_linked
        self.entity_type = entity_type
        self.generic_entity_file_type = generic_entity_file_type

    @staticmethod
    def deserialize_entity_type(entity_type):
        return EntityType.from_str(entity_type)


class ColumnDetails(BaseModel):
    """
    Represents a column and its corresponding details.

    :type column_type: :class:`~ldclient.enums.AddableColumnType`
    :param column_type: The type of column.

    :type name: :class:`str`
    :param name: The display name of the column.

    :type supplementary: :class:`bool`
    :param supplementary: Whether or not the column is supplementary.

    :type units: :class:`str`
    :param units: The units of the column.

    :type value_type: :class:`~ldclient.enums.ValueType`
    :param value_type: The type of cells in the column.

    :type aggregate: :class:`bool`
    :param aggregate: Whether or not the column is aggregated.

    :type clustered: :class:`bool`
    :param clustered: Whether or not the column is clustered.

    :type data_source_id: :class:`str`
    :param data_source_id: The ID of the data source for the column.

    :type min_value: :class:`float`
    :param min_value: The minimum value for the column, if applicable.

    :type max_value: :class:`float`
    :param max_value: The maximum value for the column, if applicable.

    :type realtime_3d: :class:`bool`
    :param realtime_3d: Whether or not the column is realtime 3D.

    :type realtime: :class:`bool`
    :param realtime: Whether or not the column is realtime.

    :type realtime_prediction_name: :class:`str`
    :param realtime_prediction_name: The realtime prediction name.

    :type assay_id: :class:`str`
    :param assay_id: The assay ID of the column.

    :type published: :class:`bool`
    :param published: Whether or not the column is visible to all projects.

    :type intra_cell_row_key: :class:`str`
    :param intra_cell_row_key: The intra cell row key.

    :type assay_default_aggregation_type: :class:`~ldclient.enums.CellAggregationType`
    :param assay_default_aggregation_type: The default aggregation type, if applicable.
    """
    _fields = [
        'column_type', 'name', 'supplementary', 'units', 'value_type',
        'aggregate', 'clustered', 'data_source_id', 'min_value', 'max_value',
        'realtime_3d', 'realtime', 'realtime_prediction_name', 'assay_id',
        'published', 'intra_cell_row_key', 'assay_default_aggregation_type'
    ]

    def __init__(self,
                 column_type=None,
                 name=None,
                 supplementary=None,
                 units=None,
                 value_type=None,
                 aggregate=None,
                 clustered=None,
                 data_source_id=None,
                 min_value=None,
                 max_value=None,
                 realtime_3d=None,
                 realtime=None,
                 realtime_prediction_name=None,
                 assay_id=None,
                 published=None,
                 intra_cell_row_key=None,
                 assay_default_aggregation_type=None):
        self.column_type = column_type
        self.name = name
        self.supplementary = supplementary
        self.units = units
        self.value_type = value_type
        self.aggregate = aggregate
        self.clustered = clustered
        self.data_source_id = data_source_id
        self.min_value = min_value
        self.max_value = max_value
        self.realtime_3d = realtime_3d
        self.realtime = realtime
        self.realtime_prediction_name = realtime_prediction_name
        self.assay_id = assay_id
        self.published = published
        self.intra_cell_row_key = intra_cell_row_key
        self.assay_default_aggregation_type = assay_default_aggregation_type

    @staticmethod
    def deserialize_column_type(column_type):
        return AddableColumnType.from_str(column_type)

    @staticmethod
    def deserialize_value_type(value_type):
        return ValueType.from_str(value_type)

    @staticmethod
    def deserialize_assay_default_aggregation_type(
            assay_default_aggregation_type):
        return CellAggregationType.from_str(assay_default_aggregation_type)


class Stats(BaseModel):
    """
    Represents statistics on a LiveReport.

    :type total_rows: :class:`int`
    :param total_rows: The count of all rows in the LiveReport.

    :type visible_rows: :class:`int`
    :param visible_rows: The count of all visible rows in the LiveReport.

    :type filtered_rows: :class:`int`
    :param filtered_rows: The count of all filtered rows in the LiveReport.

    :type hidden_rows: :class:`int`
    :param hidden_rows: The count of all hidden rows in the LiveReport.

    :type frozen_rows: :class:`int`
    :param frozen_rows: The count of all frozen rows in the LiveReport.
    """
    _fields = [
        'total_rows', 'visible_rows', 'filtered_rows', 'hidden_rows',
        'frozen_rows'
    ]

    def __init__(self,
                 total_rows=None,
                 visible_rows=None,
                 filtered_rows=None,
                 hidden_rows=None,
                 frozen_rows=None):
        self.total_rows = total_rows
        self.visible_rows = visible_rows
        self.filtered_rows = filtered_rows
        self.hidden_rows = hidden_rows
        self.frozen_rows = frozen_rows


class OriginalStructure(BaseModel):
    """
    Represents the original structure of the compound

    :type structure_id: :class:`int`
    :param: structure_id: The ID of the structure

    :type structure: :class:`str`
    :param structure: The structure of the compound
    """
    _fields = ['structure_id', 'structure']

    def __init__(self, structure_id=None, structure=None):
        self.structure_id = structure_id
        self.structure = structure


class ConfigSearchResponse(BaseModel):
    """
    ConfigSearchResponse class

    :type results: :class:`list` of :class:`~ldclient.models.Property`
    :param results: A list of the individual property values

    """
    _fields = ['results']

    def __init__(self, results=None):
        self.results = results

    def serialize_results(self):
        return Property.as_list(self.results)

    @staticmethod
    def deserialize_results(results):
        return Property.from_list(results)


class GenericEntityParseResponse(BaseModel):
    """
    GenericEntityParseResponse class

    :type parsed_entity_data: class:`~responses.ParsedGenericEntityData`
    :param parsed_entity_data: Data in form of fields for the parsed response

    :type column_metadata: :class:`dict`
    :param column_metadata: map of column name to column ID & containing information about the parsed file
    """
    _fields = ['parsed_entity_data', 'column_metadata']

    def __init__(self, parsed_entity_data=None, column_metadata=None):
        self.parsed_entity_data = parsed_entity_data
        self.column_metadata = column_metadata

    def serialize_parsed_entity_data(self):
        return ParsedGenericEntityData.as_list(self.parsed_entity_data)

    @staticmethod
    def deserialize_parsed_entity_data(parsed_entity_data):
        return ParsedGenericEntityData.from_list(parsed_entity_data)


class EntityAliasSearchResponse(BaseModel):
    """
    EntityAliasSearchResponse class

    :type results: :class:`list` of :class:`EntityAliasResult`
    :param results: The result associated with the the alias of the entity
    """
    _fields = ['results']

    def __init__(self, results=None):
        self.results = results

    def serialize_response(self):
        return EntityAliasResult.as_list(self.results)

    @staticmethod
    def deserialize_response(results):
        return EntityAliasResult.from_list(results)


class ParsedGenericEntityData(BaseModel):
    """
    ParsedGenericEntityData class

    :type index: class:`int`
    :param index: The index of the row in the parsed data for the generic entity

    :type alias: class:`str`
    :param alias: The alias used for the data

    :type success: class:`bool`
    :param success: The flag to denote if it was a success or failure

    :type messages: :class:`list` of :class:`str`
    :param messages: The messages associated with the data

    :type availability: :class:`~ldclient.enums.EntityAliasAvailability`
    :param availability: Describes the availability status of associated data

    :type properties: :class:`list` of :class:`dict`
    :param properties: A list of the map of property names to the corresponding property values

    """
    _fields = [
        'index', 'alias', 'success', 'messages', 'availability', 'properties'
    ]

    def __init__(self,
                 index=None,
                 alias=None,
                 success=None,
                 messages=None,
                 availability=None,
                 properties=None):
        self.index = index
        self.alias = alias
        self.success = success
        self.messages = messages
        self.availability = availability
        self.properties = properties

    def __eq__(self, other):
        if not isinstance(other, ParsedGenericEntityData):
            return NotImplemented
        return self.index == other.index and self.alias == other.alias and self.success == other.success and \
               self.messages == other.messages and self.availability == other.availability and \
               self.properties == other.properties

    @staticmethod
    def deserialize_availability(availability):
        return EntityAliasAvailability.from_str(availability)


class EntityAliasResult(BaseModel):
    """
    EntityAliasResult class

    :type alias: :class:`str`
    :param alias: The alias used for the data

    :type availability: :class:`~ldclient.enums.EntityAliasAvailability`
    :param availability: Describes the availability status of associated data

    """
    _fields = ['alias', 'availability']

    def __init__(self, alias=None, availability=None):
        self.alias = alias
        self.availability = availability

    @staticmethod
    def deserialize_availability(availability):
        return EntityAliasAvailability.from_str(availability)


class GenericEntityImportResponse(BaseModel):
    """
    :type index: :class:`int`
    :param index: The index associated with the import response

    :type entity_id: :class:`str`
    :param entity_id: The numeric entity ID of the row to remove

    :type all_ids: :class:`list` of :class:`str`
    :param all_ids: The list of the numeric entity ID of the row & the corresponding numeric generic entity ID

    :type messages: :class:`list` of :class:`str`
    :param messages: The messages associated with the data

    :type success: class:`bool`
    :param success: The flag to denote if it was a success or failure

    :type observations_imported: :class:`int`
    :param observations_imported: Number of observations included in the import

    :type observations_skipped: :class:`int`
    :param observations_skipped: Number of observations skipped while importing

    """
    _fields = [
        'index', 'entity_id', 'all_ids', 'messages', 'success',
        'observations_imported', 'observations_skipped'
    ]

    def __init__(self,
                 index=None,
                 entity_id=None,
                 all_ids=None,
                 messages=None,
                 success=None,
                 observations_imported=None,
                 observations_skipped=None):
        self.index = index
        self.entity_id = entity_id
        self.all_ids = all_ids
        self.messages = messages
        self.success = success
        self.observations_imported = observations_imported
        self.observations_skipped = observations_skipped


class GenericEntityImportTaskResult(BaseModel):
    """
    The response of the Generic Entity import

    :type import_responses: :class:`list` of :class:`GenericEntityImportResponse`
    :param import_responses: List of all the import responses associated with the generic entity import

    :type message: :class:`str`
    :param message: The message containing information about the imported entities

    :type addable_columns: :class:`list` of :class:`int`
    :param addable_columns: List containing the addable column Ids in the result
    """
    _fields = ['import_responses', 'message', 'addable_columns']

    def __init__(self, import_responses=[], message=None, addable_columns=None):
        self.import_responses = import_responses
        self.message = message
        self.addable_columns = addable_columns

    def serialize_import_responses(self):
        return GenericEntityImportResponse.as_list(self.import_responses)

    @staticmethod
    def deserialize_import_responses(import_responses):
        return GenericEntityImportResponse.from_list(import_responses)
