import io
import base64
import requests
import pandas as pd
import os
import warnings
from .api.utils import return_curl_or_response
from .write import ViWriteClient
from .analytics.client import ViAnalyticsClient
from .utils import decorate_functions_by_argument, set_default_collection
from .errors import LoginError, APIError

class ViClient(ViWriteClient, ViAnalyticsClient):
    """
        The main Vi client with most of the available read and write methods available to it.

        Parameters:
            username:
                your username for accessing vectorai
            api_key:
                your api key for accessing vectorai
            url:
                url of the deployed vectorai database

        Example:
            >>> from vectorai.client import ViClient
            >>> vi_client = ViClient(username, api_key, vectorai_url)
            >>> vi_client.list_collections()
    """

    def __init__(self,
        username: str=None,
        api_key: str=None,
        # Old API URL: https://vecdb-aueast-api.azurewebsites.net
        # url: str="https://vectorai-development-api-vectorai-test-api.azurewebsites.net/",
        url: str="https://vectorai-development-api.azurewebsites.net",
        analytics_url="https://vector-analytics.vctr.ai", verbose: bool = True) -> None:
        super().__init__(username, api_key, url)
        if username is None:
            if 'VI_USERNAME' not in os.environ.keys():
                raise APIError("Specify username of set VI_USERNAME as an environment variable.")
            username = os.environ['VI_USERNAME']

        if api_key is None:
            if 'VI_API_KEY' not in os.environ.keys():
                raise APIError("Specify VectorAI API key VI_API_KEY as an environment variable.")
            api_key = os.environ['VI_API_KEY']

        self.username = username
        self.api_key = api_key
        self.url = url
        self.analytics_url = analytics_url

        if verbose:
            self.check_login_details()
            print(
                f"Logged in. Welcome {self.username}. To view list of available collections, call list_collections() method."
            )

    def check_login_details(self):
        try:
            self.list_collections()
        except:
            raise LoginError("Username, api key or url is incorrect.")


def request_api_key(username: str, email:str, description:str="I'd like to try it out.", referral_code: str="github_referred",
return_curl: bool=False, **kwargs):
    """
        Request an api key
        Make sure to save the api key somewhere safe. If you have a valid referral code, you can recieve the api key more quickly.

        Args:
            username:
                Username you'd like to create, lowercase only
            email:
                Email you are using to sign up
            description:
                Description of your intended use case
            referral_code:
                The referral code you've been given to allow you to register for an api key before others
    """
    params = {
        "username": username,
        "email": email,
        "referral_code": referral_code,
        "description": description,
    }
    params.update(kwargs)
    response = requests.post.json()(
        url="{}/project/request_api_key".format("https://api.vctr.ai"),
        json=params
    )
    return return_curl_or_response(response, 'json', return_curl)

@decorate_functions_by_argument(set_default_collection, 'collection_name')
class ViCollectionClient(ViClient):
    """
        The Vi client when you are mainly working with 1 client.

        Args:
            username:
                your username for accessing vecdb
            api_key:
                your api key for accessing vecdb
            url:
                url of the deployed vecdb database
            collection_name:
                The name of the collection

        Example:
            >>> from vectorai.client import ViClient
            >>> vi_client = ViClient(username, api_key, collection_name, vectorai_url)
            >>> vi_client.insert_documents(documents)
    """
    def __init__(self, collection_name: str, username: str, api_key: str, url: str="https://api.vctr.ai", verbose: bool=True) -> None:
        warnings.warn("ViCollectionClient is no longer supported and will be deprecated in the near future." + \
            "Stick to using ViClient in the future.")
        if username is None:
            if 'VI_USERNAME' not in os.environ.keys():
                raise APIError("Specify username of set VI_USERNAME as an environment variable.")
            username = os.environ['VI_USERNAME']

        if api_key is None:
            if 'VI_API_KEY' not in os.environ.keys():
                raise APIError("Specify VectorAI API key VI_API_KEY as an environment variable.")
            api_key = os.environ['VI_API_KEY']

        self.username = username
        self.api_key = api_key
        self._collection_name = collection_name
        self.url = url
        if verbose:
            self.check_login_details()
            print(
                f"Logged in. Welcome {self.username}. To view list of available collections, call list_collections() method."
            )
            setattr(self, 'decorator_called', False)

    @property
    def collection_name(self) -> str:
        return self._collection_name

    @collection_name.setter
    def collection_name(self, value: str) -> None:
        self._collection_name = value

    @collection_name.getter
    def collection_name(self) -> str:
        return self._collection_name
