import sys
sys.path.append('../../')
from RedisQ.GPUWorker import GPUWorker
from redis import Redis
from RedisQ.Base.Qjob import BaseJob
from RedisQ.Base.Qlist import LQ, LW, LD, HS, HJ
#from DICOM.AlgorithmAPI.main_interface import predictLungCancer
from pyseri.serializer import serializer
import json
import csv
import requests
import os


class DICOMPredictionContent(object):
    # those data is used for testing
    api = 'http://192.168.1.122:8000/api/v1/'
    image = 'images/?accession_id=4&limit=200&ordering=id'
    api = 'http://192.168.1.122:8000/api/v1/'
    patient = 'patients/'
    patient_id = '1'
    case = 'cases/'
    case_id = '2351cb63-ea0a-4f40-8fed-5a82761adb7e'
    accession = 'accessions/'
    accession_id = '1'
    cad = 'cads/'


class DICOMJob(BaseJob):

    content = DICOMPredictionContent()


class DICOMConfig(object):

    gpu_load = 0.3
    gpu_memory = 0.3
    docker_path = './test'
    docker_image_tag = 'test_work'
    res_base = 'DICOM/res'
    des_base = 'workout/DICOM/des'

    @property
    def gpu_fraction(self):
        return (self.gpu_memory + self.gpu_load) * 0.5


def payload(job, config):
    print('playload running...')
    # get job
    content = job.content
    # get api information
    print('get resource info')
    response = requests.get(content.api + content.image)
    if response.status_code != 200:
        raise Exception("can't get resource information")
    for image in response.json().get('results'):
        raw_uri = image.get('raw_file_path', None)
        id = image.get('id', None)
        if raw_uri and id is None:
            raise Exception("can get resource information 'cause raw_uri or id is not in the response")
        # judge if the raw file has been down
        filename = raw_uri.split('/')[-1]
        res = '{base}/{id}_{filename}'.format(
            base=config.res_base,
            id=id,
            filename=filename
        )
        if not os.path.isfile(res):
            print('download raw file')
            response = requests.get(raw_uri)
            if response.status_code != 200:
                raise Exception("can't download raw files {},{}".format(raw_uri, id))
        # set file path
        with open(res, 'wb+') as f:
            f.write(response.content)
    print('ready to predict')
    des = '{base}/{filename}/'.format(
    base=config.des_base,
    filename=filename.split('.')[0]
    )
    # write content
    # make destenation path if there not be
    if not os.path.isdir(des):
        os.mkdir(des)
    # run algorithm if there is not result
    files = os.listdir(des)
    if not files:
        print('prediction...')
        try:
#            predictLungCancer(dcm_dir=res,model_dir='DICOM/models',tgt_dir=des,tmp_dir='/tmp/plc/',pci_id='1')
            pass
        except Exception as e:
            print(e)

    metadata = job.create_metadata()
    for file_name in files:
        if file_name.endswith('png') or file_name.endswith('jpg') or file_name.endswith('jpeg'):
            metadata.images.append(file_name)
        if file_name.endswith('csv'):
            with open('{des}/{file_name}'.format(des=des,file_name=file_name), 'r') as f:
                reader = csv.reader(f)
                rows = []
                for row in reader:
                    rows.append(row)
                for kvs in zip(*rows):
                    key = kvs[0]
                    values = kvs[1:]
                    metadata.features[key] = values

    if not os.path.isfile('{des}/metadata.json'.format(des=des)):
        print('write metadata')
        with open('{des}/metadata.json'.format(des=des), 'w+') as f:
            j = serializer.dump(metadata)
            f.write(json.dumps(j))
    print('payload done')
    print('polling...')


def run_worker(host, port):
    conn = Redis(host=host, port=port)
    config = DICOMConfig()
    worker = GPUWorker(connection=conn, config=config, job_hash=HJ, sign_hash=HS,
                       queue_list=LQ, working_list=LW, done_list=LD)
    print('polling...')
    worker.polling(config=config, payload=payload)

if __name__ == '__main__':
    run_worker(host='192.168.1.122', port='6389')
