import time
import os
import sys
import logging
import shutil
import subprocess
import uuid
import lazy_logger

from collections import OrderedDict
from django.conf import settings
from datetime import datetime
from matrix.matrix import NimbusFATP, NimbusMLB

from .crawler import Crawler
from .crawler_selenium import Crawlers

from .models import Nimbussetting, Buildmatrix


logger = logging.getLogger(__name__)
#logger = lazy_logger.get_logger(__name__)


def log_time():
    """return str time
    """
    return str(time.strftime("%Y%m%d%H%M", time.localtime(time.time())))


def get_log(file, title):
    with open(file, 'rb') as fp:
        logs = OrderedDict([(title, fp.read())])
    return logs


def cntlm():
    p = subprocess.Popen(["ps", "-a"], stdout=subprocess.PIPE)
    out, err = p.communicate()
    if b'cntlm -v' in out:
        logger.info('cntlm is running.')
    else:
        #cmd = ['cntlm', '-v']
        #process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
        logger.info('please check cntlm service.')
        raise RuntimeError('please check cntlm service.')


def order_fruit(fruit, num_fruit):
    time.sleep(num_fruit)   # e.g. 2 apples take 2 secs
    return '%s_%s' % (fruit, num_fruit)


def task_job(sleep_time):
    time.sleep(sleep_time)
    return str(datetime.strftime(datetime.now(),'%Y-%m-%d-%H'))


def crawler_job(url):
    crawler = Crawler()
    driver = crawler.driver()
    driver.get(url)
    pageSource = driver.page_source
    driver.close()
    return pageSource


def create_folder(path):
    """執行流程
    先確認是否存在資料夾路徑，沒有則建立
    """
    if not os.path.isdir(path):
        logger.info('create folder: {0}'.format(path))
        os.makedirs(path)
    else:
        logger.info('folder: {0} exist.'.format(path))


def move_data(source, target_path):
    """執行流程
    先確認是否存在檔案，沒有則移動檔案到目標位置
    """
    if not os.path.exists(target_path):
        logger.info('move file {0} to {1}'.format(source, target_path))
        shutil.copy(source, target_path)
    else:
        logger.info('Exist {0} in {1}'.format(source, target_path))


def transfer_data(file, product, build, category, sheet, version, path, matrix_output=None, config_output=None):
    """執行流程
    轉換資料與儲存存在與下載資料夾同一位置。
    接著複製檔案到對應得位置。
    """
    file_name = os.path.split(file)[1]
    matrix_name = 'Matrix{0}.csv'.format(category)
    config_name = 'Matrix{0}_config.csv'.format(category)
    if matrix_output is None:
        matrix_output = os.path.join(path, category, matrix_name)
    else:
        matrix_output = os.path.join(path, category, matrix_output)

    if config_output is None:
        config_output = os.path.join(path, category, config_name)
    else:
        config_output = os.path.join(path, category, config_output)

    logger.info('file: {0}'.format(file))
    logger.info('matrix_output:{0}, config_output:{1}'.format(matrix_output, config_output))
    
    try:
        if str(category).upper() == 'FATP':
            nimbus = NimbusFATP(file=file, sheet=sheet)
        elif str(category).upper() == 'MLB':
            nimbus = NimbusMLB(file=file, sheet=sheet)
        else:
            raise ValueError('category should be FATP or MLB')
        nimbus.matrix_output(output=matrix_output)
        nimbus.config_output(output=config_output)
    except Exception as e:
        raise e

    try:
        create_folder(path=os.path.join(path, category, product))                    #product folder
        create_folder(path=os.path.join(path, category, product, build))             #build folder
        create_folder(path=os.path.join(path, category, product, build, version))    #version folder

        move_data(source=file, target_path=os.path.join(path, category, product, build, version, file_name))
        move_data(source=matrix_output, target_path=os.path.join(path, category, product, build, version, matrix_name))
        move_data(source=config_output, target_path=os.path.join(path, category, product, build, version, config_name))
    except Exception as e:
        raise e

    # create .dat for evan, short term solution.
    with open(os.path.join(path, category, '{0}.dat'.format(category)), 'w') as fp:
        log_time = str(time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime(time.time())))
        fp.write(log_time+'\n'+str(version).upper().replace('V',''))


def configure_logging(log_path):
    #log_path = os.path.join(os.getcwd(), 'logs', log_time()+'-nimbus.log') #TODO(log 名稱應該用 uuid)
    logging.basicConfig(
        filename=log_path,
        level=logging.INFO,
        format='%(asctime)s:%(name)s:%(levelname)s:%(message)s',
    )
    console = logging.StreamHandler()
    aformat = logging.Formatter('%(asctime)s:%(name)s:%(levelname)s:%(message)s')
    console.setFormatter(aformat)
    logger.addHandler(console)
    logger.info('logger file: {0}'.format(log_path))


def crawler_matrix_job(product, build, category, sheet, download_path):
    """參數說明:
    product = 產品代號, 對應資料庫 NimbusSetting, ex:Jedi
    build = 試產階段, 對應資料庫 NimbusSetting, ex:P2
    category = 哪個線, 對應資料庫 Buildmatrix, ex:FATP, MLB
    sheet = 檔案內的 sheet, 對應 Buildmatrix, ex:FATP, D20-D201 MLB
    download_path = 設定的下載位置, ex:./downloads
    """
    log_path = os.path.join(os.getcwd(), 'logs', log_time()+'-'+str(uuid.uuid1())+'.log')
    lazy_logger.log_to_console(logger)
    lazy_logger.log_to_rotated_file(logger=logger,file_name=log_path)
    logger.info('logger file: {0}'.format(log_path))

    #try:
    #    cntlm()
    #except Exception as e:
    #    raise e

    try:
        logger.info('start crawler Nimbus BuildMatrix.')
        nimbus = Nimbussetting.objects.filter(product=product, build=build)[0]   #setting 
        matrix = Buildmatrix.objects.filter(build=nimbus, category=category)[0]
        crawler = Crawlers(
            account=nimbus.account, password=nimbus.password,
            url=matrix.url, category=category,
            download_path=download_path, log_path=log_path
        )
        ret = crawler.download_matrix(version=matrix.last_version)
        if type(ret) is not type(OrderedDict()):   # 確保不正確錯誤噴出的錯誤格式錯誤
            ret = OrderedDict((('ret', 255), ('status', ret), ('version', '')))
    except Exception as e:
        #raise e
        ret = OrderedDict((('ret', 255), ('status', e), ('version', '')))
    
    try:
        logger.info('start conver nimbus build matrix data.')
        file = crawler.download_exist()
        if file is not None: #如果下載成功才進行
            file = os.path.join(download_path, category, file)
            transfer_data(   #轉檔，並根據 project/build/version 將檔案移動到正確位置
                file=file, product=product, build=build, category=category,
                sheet=sheet, version=ret['version'], path=download_path
            )
            logger.info('success conver nimbus build matrix data.')
        else:
            logger.info('version is not change, pass covert data.')

        logger.info('ret: {0}.'.format(ret))
        if ret['ret'] == 0:   #更新其實可以挪到上面做，不然檔案存在與否與回傳值 = 0 都是判斷是一樣要執行這段
            matrix.last_version = ret['version']
            matrix.save()
            logger.info('success save latest version in DB.')
        else:
            logger.info('DB version not change.')
    except Exception as e:
        #raise e
        ret = OrderedDict((('ret', 255), ('status', e), ('version', '')))
    
    logs = get_log(file=log_path, title='crawler_matrix_job')
    ret.update(logs)
    return ret

