# -*- coding: utf-8 -*-
"""
SPDX-License-Identifier: MIT
"""

# pylint: disable=too-many-lines,line-too-long
#
import time
import zlib
import json
from contextlib import closing
#
from urllib.parse import urlparse, urlencode
from urllib.request import urlopen, Request
from urllib.error import HTTPError
from io import BytesIO



class WebResource(object):
    """
    Download url
    
    
    to (de-)compress deflate format, use wbits = -zlib.MAX_WBITS
    to (de-)compress zlib format, use wbits = zlib.MAX_WBITS
    to (de-)compress gzip format, use wbits = zlib.MAX_WBITS | 16

    """

    def __init__(self, pAddon, pUrl, pHeader = None, pAbortHook = None, pProgressListener = None, pChunkSize=8192, pTimeout=10, pUseragent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0"):
        self.addon = pAddon
        self.logger = pAddon.createLogger('WebResource')
        self.abortHook = pAddon.getAbortHook()
        self.progressListener = pAddon.getProgressDialog().updateProgress
        #
        self.connectionTimeout = pTimeout
        self.chunkSize = pChunkSize
        if pHeader == None:
            self.header = {
                'Accept-Encoding':'gzip, deflate',
                'User-Agent':pUseragent
            }
        else:
            self.header = pHeader    
        #
        self.url = pUrl
        #
        self.startTime = 0

    def retrieveAsString(self, postData=None):
        #
        self.startTime = time.time()
        if postData is not None:
            request = Request(
                self.url,
                data=json.dumps(postData).encode("utf-8")
            )
            request.add_header("Content-Type", "application/json")
        else:
            request = Request(self.url)
        self.logger.debug('url {}',self.url)
        #
        for kkey,vvalue in list(self.header.items()):
            request.add_header(kkey, vvalue)
            self.logger.debug('header {} {}',kkey,vvalue)
        #
        rsArrayBuffer = []
        #
        with closing(urlopen(request, timeout=self.connectionTimeout)) as response:
            #
            content_encoding = response.info().get('Content-Encoding')
            self.logger.debug('content_encoding {}', content_encoding )
            #
            content_length = response.info().get("Content-Length")
            content_length = int(content_length) if content_length else self.chunkSize*100
            self.logger.debug('content_length {}',content_length )
            #
            cycleCnt = 1
            #
            if content_encoding == 'gzip':
                decomp = zlib.decompressobj(16+zlib.MAX_WBITS)
            elif content_encoding == 'deflate':
                decomp = zlib.decompressobj(-zlib.MAX_WBITS)
            else:
                decomp = None
            #
            buffer=response.read(self.chunkSize)
            #
            while buffer and not self.abortHook():
                if decomp:
                    outstr = decomp.decompress(buffer)
                else:
                    outstr = buffer
                #
                rsArrayBuffer.append(outstr)
                buffer=response.read(self.chunkSize)
                cycleCnt += 1
                self.progressListener(cycleCnt*self.chunkSize, content_length)
            #
            if decomp:
                outstr = decomp.flush()
                rsArrayBuffer.append(outstr)
            #
            outputString = b''.join(rsArrayBuffer)
            #
        self.logger.debug('retrieveAsString {} bytes(s) in {} sec for {}', content_length, round(time.time() - self.startTime, 4), self.url)
        return outputString
            
    def _progressListener(self, pDone, pTotal):
        pass
