from abc import abstractmethod
import requests
import json
import re

class SearchAPIClient():
    """
    Search Engine API Client Base Class
    """
    def __init__(self, endpoint: str, max_results: int, max_results_per_q: int, min_index: int, headers: dict = None, params: dict = None):
        self.headers = headers
        self.params = params
        self.endpoint = endpoint
        self.max_results = max_results
        self.max_results_per_q = max_results_per_q
        self.min_index = min_index
        self.response = None

    @abstractmethod
    def _check_value(self, **kwargs):
        """
        Verify value of keyworded arguments to be passed to the request's parameters.
        """
        pass

    @abstractmethod
    def _parse_response(self):
        """
        Extract items (and their specified parameters) from the request's response and return them
        in the form of a list of items (each item being a dict).
        """
        pass

    def search(self, query, **kwargs):
        """
        Execute search request to the specified endpoint from a defined query and parameters.
        Returns response in a list of dictionaries (one dict per item) generated by the 
        _parse_response method.
        """
        if not query:
            raise ValueError("Expected a query")
        self._check_value(**kwargs)

        self.params.update(q=query, **kwargs)
        self.response = requests.get(self.endpoint, headers=self.headers, params=self.params).json()
        return self._parse_response()

    def generate_filename_from_query(self, query: str, idx: int, ext: str = None):
        """
        Generate a filename from the specified formatted query with the file extension and idx
        """
        if not ext:
            ext = 'jpeg'
        return f'{query}_{str(idx).zfill(5)}.{ext}'

    def add_filename_to_search_dict(self, search, query, offset = 0):
        """
        Add a filename to each link returned from the search results, which are in dict format.
        """
        [s.update(file=self.generate_filename_from_query(query, i + offset, s['type'])) for i,s in enumerate(search)]
        return search