import requests
import json
import time
import base64

class Api:
    def __init__(self,url,username='',password=''):
        basic = username+':'+password
        auth = base64.b64encode(basic.encode(encoding = 'utf-8')).decode('utf-8');
        self.url = url;
        self.headers = {
            'Content-Type': 'application/json',
            'Authorization': 'Basic '+ auth
        }
        self.id = 0;
        
    def call(self,func,params):
        self.id = self.id+1;
        req_id = self.id;
        payload = {
            "method":func,
            "params": params,
            "jsonrpc": "2.0",
            "id": req_id,
        }
        response = requests.post(self.url, data=json.dumps(payload), headers=self.headers).json()
        if 'error' in response:
            raise Exception(response['error']);
        return response['result']

    def __getattr__(self,name):
        if name in self.__dict__:
            return self.__dict__[name]
        def func(*args):
            return self.call(name,args)
        return func

    def get_all_info(self,fields = '*'):
        """请求全部股票信息
        
        [可以根据fields指定获取的字段]
        
        Keyword Arguments:
            fields {str} -- [description] (default: {'*'})
        
        Returns:
            [type] -- list of dict
        """
        return self.call('get_all_info',[fields]);

    def get_trading_dates_by_date_range(self,start,end,exchange='sh'):
        """获取指定日期内的交易日
        
        [description]
        
        Arguments:
            start {[type]} -- [description]
            end {[type]} -- [description]
        
        Keyword Arguments:
            exchange {str} -- [description] (default: {'sh'})
        
        Returns:
            [type] -- [type] -- list of str like ['2016-01-01']
        """
        return self.call('get_trading_dates_by_date_range',[start,end,exchange]);


    def get_symbols_by_industry(self,industry):
        """根据行业获取股票代码
        
        [description]
        
        Arguments:
            industry {[type]} -- [行业名称]
        
        Returns:
            [type] -- list of str(symbols)
        """
        return self.call('get_symbols_by_industry',[industry]);

    def get_symbols_by_concept(self,concept):
        """根据概念获取股票代码
        
        [description]
        
        Arguments:
            industry {[type]} -- [行业名称]
        
        Returns:
            [type] -- list of str(symbols)
        """        
        return self.call('get_symbols_by_concept',[concept]);

    def get_symbols_by_index(self,index):
        """根据股票标签获取股票代码
        ！！待完善
        支持   
            hs300s : 沪深300
            sz50s  : 上证50成份股
            zz500s : 中证500成份股
        Arguments:
            index {[type]} -- [description]
        
        Returns:
            [type] -- [description]
        """
        return self.call('get_symbols_by_index',[index]);

    def get_all_symbols_by_date(self,date):
        """获取指定交易日上市的股票代码列表
        Arguments:
            date {[type]} -- [description]
        Returns:
            [type] -- list of str (symbol)
        """
        return self.call('get_all_symbols_by_date',[date]);

    def get_trading_dates_by_date_range(self,start,end,exchange='sh'):
        """获取指定日期内的交易日
        
        [description]
        
        Arguments:
            start {[type]} -- [description]
            end {[type]} -- [description]
        
        Keyword Arguments:
            exchange {str} -- [description] (default: {'sh'})
        
        Returns:
            [type] -- [type] -- list of str like ['2016-01-01']
        """
        return self.call('get_trading_dates_by_date_range',[start,end,exchange]);


    def get_last_dailybars_by_date(self,symbol, num, endDate = None, adjType = 'qfq'):
        """获取最近几天的日线，16:00后包含当天
        Arguments:
            symbol {str} -- 股票代码
            num {int} -- 天数
        
        Keyword Arguments:
            endDate {[type]} -- [description] (default: {None})
            adjType {str} -- [description] (default: {'none'})
        
        Returns:
            [type] -- list of dict
        """
        return self.call('get_last_dailybars_by_date',[symbol, num, endDate,adjType]);
    
    def get_dailybars_by_date_range(self,start, end, symbols = None, adjType = 'qfq'):
        """获取指定日期的日线，不包含当天
            必须指定股票代码，否则返回空列表
            时间区间不大于1个月（31天）
        Arguments:
            start {str} -- 开始日期
            end {str} -- 结束日期
            symbols {list} -- 股票代码列表
        
        Keyword Arguments:
            adjType {str} -- 复权类型 (default: {'none'})
        
        Returns:
            [type] -- list of dict
        """
        return self.call('get_dailybars_by_date_range',[start, end, symbols, adjType]);
    
    def get_daily_bars(self,symbol, start, end, adjType = 'qfq'):
        """获取单只股票交易bar
            支持超过30天
        Arguments:
            symbol {[type]} -- 股票代码
            start {str} -- 开始日期
            end {str} -- 结束日期
        
        Keyword Arguments:
            adjType {str} -- [description] (default: {'none'})
        
        Returns:
            [type] -- list of dict
        """
        return self.call('get_daily_bars',[symbol, start, end, adjType]);
    
    def get_bars_by_date(self,symbols, date):
        """获取多只股票指定日的交易数据
        Arguments:
            symbols {list} -- 股票代码列表
            date {[type]} -- [description]
        Returns:
            [type] -- [description]
        """
        return self.call('get_bars_by_date',[ymbols, date]);
    

    def get_bars_of_date(self,date, isOpen = 1):
        """获取指定交易日的全部股票行情
        
        Arguments:
            date {str} -- 日期
        
        Keyword Arguments:
            isOpen {number} -- 是否包含停牌股票（使用上一日） (default: {1})
        
        Returns:
            [type] -- [description]
        """
        return self.call('get_quotations_of_date',[date, isOpen]);

    def get_stock_trading_statics_by_date(self,symbol,end_date=None):
        return self.call('get_stock_trading_statics_by_date',[symbol,end_date]);
        
    def get_all_stock_trading_statics_by_date(self,end_date):
        return self.call('get_all_stock_trading_statics_by_date',[end_date]);
        