# coding:utf-8
"""
批量任务相关的 XML 解析器类

支持以下操作：
- KS3PutObjectDataRedundancyTransition: 批量转换为同城冗余
- KS3RestoreObject: 批量解冻
- KS3PutObjectAcl: 批量修改ACL
- KS3DeleteObject: 批量删除

相关辅助类：
- KS3AccessControlList: AccessControlList 结构
- KS3Grant: Grant 结构（包含 Grantee 和 Permission）
"""

from ks3.responseResult import ResponseMetadata


class KS3PutObjectDataRedundancyTransition(object):
    """
    批量转换为同城冗余操作参数
    """
    def __init__(self, data_redundancy_type=None):
        self.data_redundancy_type = data_redundancy_type

    def to_xml(self):
        s = '<KS3PutObjectDataRedundancyTransition>\n'
        if self.data_redundancy_type is not None:
            s += '    <DataRedundancyType>%s</DataRedundancyType>\n' % self.data_redundancy_type
        s += '</KS3PutObjectDataRedundancyTransition>\n'
        return s

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        if name == 'DataRedundancyType':
            self.data_redundancy_type = value


class KS3RestoreObject(object):
    """
    批量解冻操作参数
    允许设置 days、tier 和 storage_class 参数
    storage_class 表示需要解冻的存储类型，可选值：ARCHIVE、COLD_ARCHIVE
    其中 days、storage_class 为必选参数，tier 为可选参数（仅在冷归档类型时可用，必选）
    """
    def __init__(self, days=None, tier=None, storage_class=None):
        self.days = days
        self.tier = tier
        self.storage_class = storage_class

    def to_xml(self):
        s = '<KS3RestoreObject>\n'
        if self.days is not None:
            s += '    <Days>%s</Days>\n' % self.days
        if self.tier is not None:
            s += '    <Tier>%s</Tier>\n' % self.tier
        if self.storage_class is not None:
            s += '    <StorageClass>%s</StorageClass>\n' % self.storage_class
        s += '</KS3RestoreObject>\n'
        return s

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        if name == 'Days':
            self.days = value
        elif name == 'Tier':
            self.tier = value
        elif name == 'StorageClass':
            self.storage_class = value


class KS3PutObjectAcl(object):
    """
    批量修改ACL操作参数

    支持两种方式：
    1. CannedAccessControlList: 预设ACL ('private' 或 'public-read')
    2. AccessControlList: 自定义ACL，包含多个Grant

    示例1 (CannedAccessControlList):
        KS3PutObjectAcl('private') 或 KS3PutObjectAcl('public-read')

    示例2 (AccessControlList with Grants):
        grants = [
            KS3Grant('12345678', 'FULL_CONTROL'),
            KS3Grant('87654321', 'READ')
        ]
        KS3PutObjectAcl(access_control_list=KS3AccessControlList(grants))
    """
    def __init__(self, canned_acl=None, access_control_list=None):
        self.canned_acl = canned_acl
        self.access_control_list = access_control_list

    def to_xml(self):
        s = '<KS3PutObjectAcl>\n'
        if self.canned_acl is not None:
            s += '    <CannedAccessControlList>%s</CannedAccessControlList>\n' % self.canned_acl
        if self.access_control_list is not None:
            s += '    <AccessControlList>\n'
            for grant in self.access_control_list.grants:
                s += '        <Grant>\n'
                s += '            <Grantee>%s</Grantee>\n' % grant.grantee
                s += '            <Permission>%s</Permission>\n' % grant.permission
                s += '        </Grant>\n'
            s += '    </AccessControlList>\n'
        s += '</KS3PutObjectAcl>\n'
        return s

    def startElement(self, name, attrs, connection):
        if name == 'AccessControlList':
            self.access_control_list = KS3AccessControlList()
            return self.access_control_list
        elif name == 'Grant':
            if self.access_control_list is None:
                self.access_control_list = KS3AccessControlList()
            grant = KS3Grant()
            self.access_control_list.grants.append(grant)
            return grant
        return None

    def endElement(self, name, value, connection):
        if name == 'CannedAccessControlList':
            self.canned_acl = value


class KS3AccessControlList(object):
    """
    AccessControlList for KS3PutObjectAcl
    """
    def __init__(self, grants=None):
        self.grants = grants if grants is not None else []

    def add_grant(self, grant):
        self.grants.append(grant)

    def startElement(self, name, attrs, connection):
        if name == 'Grant':
            grant = KS3Grant()
            self.grants.append(grant)
            return grant
        return None

    def endElement(self, name, value, connection):
        pass


class KS3Grant(object):
    """
    Grant for KS3PutObjectAcl
    包含 Grantee 和 Permission
    """
    def __init__(self, grantee=None, permission=None):
        self.grantee = grantee
        self.permission = permission

    def to_xml(self):
        s = '<Grant>\n'
        s += '    <Grantee>%s</Grantee>\n' % self.grantee
        s += '    <Permission>%s</Permission>\n' % self.permission
        s += '</Grant>\n'
        return s

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        if name == 'Grantee':
            self.grantee = value
        elif name == 'Permission':
            self.permission = value


class KS3DeleteObject(object):
    """
    批量删除操作参数
    """
    def __init__(self):
        pass

    def to_xml(self):
        return '<KS3DeleteObject>\n</KS3DeleteObject>\n'

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        pass


class JobOperation(object):
    """
    任务操作
    支持多种操作类型同时设置：
    - KS3RestoreObject: 批量解冻
    - KS3PutObjectAcl: 批量修改ACL
    - KS3DeleteObject: 批量删除
    - KS3PutObjectDataRedundancyTransition: 批量转为同城冗余
    """
    def __init__(self, data_redundancy_transition=None, restore_object=None,
                 put_object_acl=None, delete_object=None):
        self.data_redundancy_transition = data_redundancy_transition
        self.restore_object = restore_object
        self.put_object_acl = put_object_acl
        self.delete_object = delete_object

    def to_xml(self):
        s = '<Operation>\n'
        if self.data_redundancy_transition is not None:
            s += '    %s' % self.data_redundancy_transition.to_xml()
        if self.restore_object is not None:
            s += '    %s' % self.restore_object.to_xml()
        if self.put_object_acl is not None:
            s += '    %s' % self.put_object_acl.to_xml()
        if self.delete_object is not None:
            s += '    %s' % self.delete_object.to_xml()
        s += '</Operation>\n'
        return s

    def startElement(self, name, attrs, connection):
        if name == 'KS3PutObjectDataRedundancyTransition':
            self.data_redundancy_transition = KS3PutObjectDataRedundancyTransition()
            return self.data_redundancy_transition
        elif name == 'KS3RestoreObject':
            self.restore_object = KS3RestoreObject()
            return self.restore_object
        elif name == 'KS3PutObjectAcl':
            self.put_object_acl = KS3PutObjectAcl()
            return self.put_object_acl
        elif name == 'KS3DeleteObject':
            self.delete_object = KS3DeleteObject()
            return self.delete_object
        return None

    def endElement(self, name, value, connection):
        pass


class JobManifestFilter(object):
    """
    任务清单过滤器
    包含 Bucket 和多个 Prefix
    """
    def __init__(self, bucket=None, prefixes=None):
        self.bucket = bucket
        self.prefixes = prefixes if prefixes is not None else []

    def add_prefix(self, prefix):
        """添加前缀"""
        if prefix is not None:
            self.prefixes.append(prefix)

    def to_xml(self):
        s = '<Filter>\n'
        if self.bucket is not None:
            s += '    <Bucket>%s</Bucket>\n' % self.bucket
        for prefix in self.prefixes:
            s += '    <Prefix>%s</Prefix>\n' % prefix
        s += '</Filter>\n'
        return s

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        if name == 'Bucket':
            self.bucket = value
        elif name == 'Prefix':
            self.prefixes.append(value)


class JobManifestLocation(object):
    """
    任务清单位置
    包含多个 Filter
    """
    def __init__(self, filters=None):
        self.filters = filters if filters is not None else []

    def add_filter(self, filter_obj):
        """添加过滤器"""
        if filter_obj is not None:
            self.filters.append(filter_obj)

    def to_xml(self):
        s = '<Location>\n'
        for f in self.filters:
            s += '    %s' % f.to_xml()
        s += '</Location>\n'
        return s

    def startElement(self, name, attrs, connection):
        if name == 'Filter':
            new_filter = JobManifestFilter()
            self.filters.append(new_filter)
            return new_filter
        return None

    def endElement(self, name, value, connection):
        pass


class JobManifestSpec(object):
    """
    任务清单规格
    """
    def __init__(self, format=None):
        self.format = format

    def to_xml(self):
        s = '<Spec>\n'
        if self.format is not None:
            s += '    <Format>%s</Format>\n' % self.format
        s += '</Spec>\n'
        return s

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        if name == 'Format':
            self.format = value


class JobManifest(object):
    """
    任务清单
    包含 Location 和 Spec 字段
    """
    def __init__(self, location=None, spec=None):
        self.location = location
        self.spec = spec

    def to_xml(self):
        s = '<Manifest>\n'
        if self.location is not None:
            s += '    %s' % self.location.to_xml()
        if self.spec is not None:
            s += '    %s' % self.spec.to_xml()
        s += '</Manifest>\n'
        return s

    def startElement(self, name, attrs, connection):
        if name == 'Location':
            self.location = JobManifestLocation()
            return self.location
        elif name == 'Spec':
            self.spec = JobManifestSpec()
            return self.spec
        return None

    def endElement(self, name, value, connection):
        pass


class CreateJobRequest(object):
    """
    创建任务请求
    """
    def __init__(self, manifest=None, operation=None, priority=None, description=None,
                 report=None, client_request_token=None):
        self.manifest = manifest
        self.operation = operation
        self.priority = priority
        self.description = description
        self.report = report
        self.client_request_token = client_request_token

    def to_xml(self):
        s = '<CreateJobRequest>\n'
        if self.manifest is not None:
            s += '    %s' % self.manifest.to_xml()
        if self.operation is not None:
            s += '    %s' % self.operation.to_xml()
        if self.priority is not None:
            s += '    <Priority>%s</Priority>\n' % self.priority
        if self.description is not None:
            s += '    <Description>%s</Description>\n' % self.description
        if self.report is not None:
            s += '    %s' % self.report.to_xml()
        if self.client_request_token is not None:
            s += '    <ClientRequestToken>%s</ClientRequestToken>\n' % self.client_request_token
        s += '</CreateJobRequest>\n'
        return s

    def startElement(self, name, attrs, connection):
        if name == 'Manifest':
            self.manifest = JobManifest()
            return self.manifest
        elif name == 'Operation':
            self.operation = JobOperation()
            return self.operation
        elif name == 'Report':
            self.report = JobReport()
            return self.report
        return None

    def endElement(self, name, value, connection):
        if name == 'Priority':
            self.priority = value
        elif name == 'Description':
            self.description = value
        elif name == 'ClientRequestToken':
            self.client_request_token = value


class JobReport(object):
    """
    任务报告配置
    """
    def __init__(self, enabled=None, bucket=None, prefix=None, report_scope=None):
        self.enabled = enabled
        self.bucket = bucket
        self.prefix = prefix
        self.report_scope = report_scope

    def to_xml(self):
        s = '<Report>\n'
        if self.enabled is not None:
            s += '    <Enabled>%s</Enabled>\n' % ('true' if self.enabled else 'false')
        if self.bucket is not None:
            s += '    <Bucket>%s</Bucket>\n' % self.bucket
        if self.prefix is not None:
            s += '    <Prefix>%s</Prefix>\n' % self.prefix
        if self.report_scope is not None:
            s += '    <ReportScope>%s</ReportScope>\n' % self.report_scope
        s += '</Report>\n'
        return s

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        if name == 'Enabled':
            self.enabled = value.lower() == 'true'
        elif name == 'Bucket':
            self.bucket = value
        elif name == 'Prefix':
            self.prefix = value
        elif name == 'ReportScope':
            self.report_scope = value


class CreateJobResult(object):
    """
    创建任务响应
    """
    def __init__(self, job_id=None, *args, **kwargs):
        self.job_id = job_id
        self.response_metadata = ResponseMetadata(**kwargs)

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        if name == 'JobId':
            self.job_id = value


class JobProgressSummary(object):
    """
    任务进度摘要
    """
    def __init__(self, total_number_of_tasks=None, number_of_tasks_succeeded=None,
                 number_of_tasks_failed=None, *args, **kwargs):
        self.total_number_of_tasks = total_number_of_tasks
        self.number_of_tasks_succeeded = number_of_tasks_succeeded
        self.number_of_tasks_failed = number_of_tasks_failed
        self.response_metadata = ResponseMetadata(**kwargs)

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        if name == 'TotalNumberOfTasks':
            self.total_number_of_tasks = value
        elif name == 'NumberOfTasksSucceeded':
            self.number_of_tasks_succeeded = value
        elif name == 'NumberOfTasksFailed':
            self.number_of_tasks_failed = value


class DescribeJobResult(object):
    """
    查询任务详情响应
    """
    def __init__(self, job_id=None, status=None, creation_time=None,
                 priority=None, description=None, manifest=None, operation=None,
                 progress_summary=None, report=None, termination_date=None,
                 *args, **kwargs):
        self.job_id = job_id
        self.status = status
        self.creation_time = creation_time
        self.priority = priority
        self.description = description
        self.manifest = manifest
        self.operation = operation
        self.progress_summary = progress_summary
        self.report = report
        self.termination_date = termination_date
        self.response_metadata = ResponseMetadata(**kwargs)

    def startElement(self, name, attrs, connection):
        if name == 'Manifest':
            self.manifest = JobManifest()
            return self.manifest
        elif name == 'Operation':
            self.operation = JobOperation()
            return self.operation
        elif name == 'ProgressSummary':
            self.progress_summary = JobProgressSummary()
            return self.progress_summary
        elif name == 'Report':
            self.report = JobReport()
            return self.report
        return None

    def endElement(self, name, value, connection):
        if name == 'JobId':
            self.job_id = value
        elif name == 'Status':
            self.status = value
        elif name == 'CreationTime':
            self.creation_time = value
        elif name == 'Priority':
            self.priority = value
        elif name == 'Description':
            self.description = value
        elif name == 'TerminationDate':
            self.termination_date = value


class JobListMember(object):
    """
    任务列表中的单个任务信息
    DescribeJobResult 的简化版，不包含 manifest、report 和 response_metadata
    """
    def __init__(self, job_id=None, status=None, creation_time=None,
                 priority=None, description=None, operation=None,
                 termination_date=None):
        self.job_id = job_id
        self.status = status
        self.creation_time = creation_time
        self.priority = priority
        self.description = description
        self.operation = operation
        self.termination_date = termination_date

    def startElement(self, name, attrs, connection):
        if name == 'Operation':
            self.operation = JobOperation()
            return self.operation
        return None

    def endElement(self, name, value, connection):
        if name == 'JobId':
            self.job_id = value
        elif name == 'Status':
            self.status = value
        elif name == 'CreationTime':
            self.creation_time = value
        elif name == 'Priority':
            self.priority = value
        elif name == 'Description':
            self.description = value
        elif name == 'TerminationDate':
            self.termination_date = value


class ListJobsResult(object):
    """
    列出任务响应
    """
    def __init__(self, jobs=None, next_token=None, *args, **kwargs):
        self.jobs = jobs if jobs is not None else []
        self.next_token = next_token
        self.response_metadata = ResponseMetadata(**kwargs)

    def startElement(self, name, attrs, connection):
        if name == 'Member':
            job = JobListMember()
            self.jobs.append(job)
            return job
        return None

    def endElement(self, name, value, connection):
        if name == 'NextToken':
            self.next_token = value


class UpdateJobPriorityResult(object):
    """
    更新任务优先级响应
    """
    def __init__(self, job_id=None, priority=None, *args, **kwargs):
        self.job_id = job_id
        self.priority = priority
        self.response_metadata = ResponseMetadata(**kwargs)

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        if name == 'JobId':
            self.job_id = value
        elif name == 'Priority':
            self.priority = int(value) if value else None