#!/usr/bin/env python
#-*- coding: utf-8 -*-
#update:2014-09-12 by liufeily@163.com

from django.core.urlresolvers import reverse
from django.http import HttpResponse,HttpResponseRedirect
from django.shortcuts import render_to_response,RequestContext
from django.contrib.auth.decorators import login_required
from mplatform.website.common.CommonPaginator import SelfPaginator
import time
from django.db import connection,transaction
from mplatform.website.settings import ISO_ROOT
from django.core.files import uploadedfile
from mplatform.utils.db import dbbase
from django.views.decorators.csrf import csrf_exempt
import os
import commands
import shutil
from  django.utils import log
import string
import threading
import re
logger = log.getLogger(__name__)

@login_required
def RebootManage(request):
    os.system("/sbin/reboot")
    return HttpResponse('success')

#@PermissionVerify()
@login_required
def ListManageDeploy(request):
    logger.debug('进入函数ListSysDeploy')
    #获得部署网络
    db = dbbase.database()
    isolist = db.select_fetchall("select id, iso_name, iso_path, iso_size,iso_desc,update_time,upgrade_result,upgrade_time from platdeploy_manage")
    for iso in isolist:
        if iso['upgrade_result'] == 'success':
            iso['upgrade_result'] = '升级成功'  
        elif iso['upgrade_result'] == 'fail':
            iso['upgrade_result'] = '升级失败'  
    kwvars = {
        'lPage':isolist,
        'request':request,
    }
    logger.debug('退出函数ListSysDeploy')
    return render_to_response('PlatDeploy/managedeploy.list.html',kwvars,RequestContext(request))


@login_required
def EditNet(request,ID):
    logger.debug('进入函数EditNet ID=%s',ID)
    #user = get_user_model().objects.get(id = ID)

    #if request.method=='POST':
    #    form = EditUserForm(request.POST,instance=user)
    #    if form.is_valid():
    #        form.save()
    #        return HttpResponseRedirect(reverse('listuserurl'))
    #else:
    #    form = EditUserForm(instance=user
    #    )

    kwvars = {
        'ID':ID,
    #    'form':form,
        'request':request,
    }
    logger.debug('退出函数EditNet')
    return render_to_response('BasicManage/net.edit.html',kwvars,RequestContext(request))

@login_required
def UpgradeManage(request,id):
    db = dbbase.database()
    isoinfo = db.select_fetchone("select iso_path from platdeploy_manage where id='%s'" % id)
    cmdstr = "massclouds-manager-upgrade  %s" % isoinfo['iso_path']
    
    (status,output) = commands.getstatusoutput(cmdstr)
    upgrade_time = time.strftime("%Y-%m-%d %H:%M:%S")
    upgrade_result = 'success'
    if status == 0:
        upgrade_result = 'success'
    else:
        logger.error('Error in UpgradeManage: %s' % output)
        upgrade_result = 'fail'
    update_sql = "update platdeploy_manage set upgrade_time='%s',upgrade_result='%s' where id='%s'" \
            % (upgrade_time,upgrade_result,id)
    db.execute(update_sql)
    return HttpResponse(upgrade_result)


    

def SaveChunkFile(infoDic,fileDic):
    file_UUID = infoDic.get("fileUUID")
    chunk_dir = ISO_ROOT + 'file_pieces_' + file_UUID + '/'
    file_name = infoDic.get("name")
    chunk_index = infoDic.get("chunk")
    src_file = fileDic.get('file')

    # 可能会出现多个线程同时创建目录的情况，忽略错误
    try:
        if not os.path.exists(chunk_dir):
            os.makedirs(chunk_dir)
    except Exception as e:
        pass
        
    chunk_path = chunk_dir + file_UUID + '__' + str(chunk_index)
    
    chunk_file = open(chunk_path, 'wb')
    for chunk in src_file.chunks():
        chunk_file.write(chunk)
    chunk_file.close()



def CombineChunks(infoDic,final_path):
    file_UUID = infoDic.get("fileUUID")
    chunk_dir = ISO_ROOT + 'file_pieces_' + file_UUID + '/'
    wholefile_size = infoDic.get("size")
    file_name = infoDic.get("name")
    chunks = infoDic.get("chunks")
    retry = 0
    timeout = False
    
    # 合并切片之前，先确认所有切片都已上传完成，如果超过 2 分钟切片还未上传完成，则取消合并
    while True:
        if retry > 120:
            timeout = True
            break
        retry = retry + 1
        finish_size = 0
        for ch in os.listdir(chunk_dir):
            finish_size = finish_size + os.path.getsize(chunk_dir + ch)
        if int(finish_size) >= int(wholefile_size):
            break
        time.sleep(1)
    
    # 开始合并
    if not timeout:
        final_file = open(final_path, 'wb')
        for i in range(int(chunks)):
            chunk_file = open(chunk_dir + file_UUID + '__' + str(i), 'rb')
            final_file.write(chunk_file.read())
            chunk_file.close()
        final_file.close()
        
    # 合并完成，删除存放切片的临时目录
    shutil.rmtree(chunk_dir)

def RenameFile(old_name):
    realname = old_name
    extname = ''
    if '.' in old_name:
        realname = old_name[:old_name.rfind('.')]
        extname = old_name[old_name.rfind('.'):]
    index = 0
    new_name = old_name
    while os.path.exists(ISO_ROOT + new_name):
        index = index + 1
        new_name = '%s(%s)%s' % (realname,str(index),extname)
    return new_name
        
@login_required
@csrf_exempt
def AddManage(request):
    if request.method=='POST':
        chunks = request.POST.get("chunks")
        chunk_index = request.POST.get("chunk")
        
        if not os.path.exists(ISO_ROOT):
            os.makedirs(ISO_ROOT)
            
        # 清除之前的碎片文件
        if chunks and chunk_index and int(chunk_index) == 0 or not chunks:
            res_listdir = os.listdir(ISO_ROOT)
            for i in res_listdir:
                if os.path.isdir(ISO_ROOT + i) and re.match('^file_pieces_\w{32}$',i):
                    shutil.rmtree(ISO_ROOT + i)

        # 保存切片文件
        if chunks: 
            th = threading.Thread(target=SaveChunkFile,args=(request.POST,request.FILES))
            th.start()
            
        file_UUID = request.POST.get("fileUUID")
        iso_name = request.POST.get("name")
        iso_path = ISO_ROOT + iso_name.encode('utf-8')
        iso_desc = request.POST.get("iso_desc")
        iso_size = request.POST.get("size")
        final_path = ISO_ROOT + file_UUID + '.iso'
#         final_name = file_UUID + '.iso'
        
        # 检测到同名文件后，自动重命名
#         if not chunks or int(chunk_index) == int(chunks) - 1: 
#             rename = False
#             if os.path.exists(iso_path):
#                 rename = True
#                 final_name = RenameFile(iso_name.encode('utf-8'))
#                 final_path = ISO_ROOT + final_name
            
        # 小文件，直接保存
        if not chunks: 
            final_file = open(final_path, 'wb')
            final_file.write(request.FILES.get('file').read())
            final_file.close()
        
        # 大文件，到达最后一片时，将切片合并（该线程应该阻塞）
        if chunks and int(chunk_index) == int(chunks) - 1: 
            th2 = threading.Thread(target=CombineChunks,args=(request.POST,final_path))
            th2.start()
            th2.join()
        
        # 保存数据库
        if not chunks or int(chunk_index) == int(chunks) - 1: 
            cursor = connection.cursor()
            cursor.execute("select COALESCE(max(id),0)+1 as new_id from platdeploy_manage")
            id = cursor.fetchone()[0]
            update_time = time.strftime("%Y-%m-%d %H:%M:%S")
            cursor.execute("INSERT INTO platdeploy_manage(id, iso_name, iso_path, iso_size,iso_desc,\
                    update_time,upgrade_time,upgrade_result) values (%s, %s, %s,%s, %s, %s,'','')", 
                    [id, iso_name, final_path,iso_size,iso_desc, update_time])
            connection.commit()
            
            # 自动重命名后，将新文件名告知前端
#             if iso_name != final_name: 
#                 return HttpResponse(final_name)
            
        return HttpResponse('')

    else:
        pass

    kwvars = {
        'request':request,
    }

    return render_to_response('PlatDeploy/manage.add.html',kwvars,RequestContext(request))

@login_required
def DeleteIso(request,id):
        db = dbbase.database()
#         idlist = request.POST.getlist('id')
#         str_id =  ""
#         logger.debug('idlist=%s',idlist)
#         for id in idlist:
#             str_id=str_id+id+","
#         str_id2 = str_id.rstrip(',')
#         print str_id2
        select_sql = "select id, iso_name, iso_path, iso_size,iso_desc,update_time from platdeploy_manage where id = %s" % id
        isolist = db.select_fetchall(select_sql)
        print isolist
        for iso in isolist:
            cmd_delete = 'rm -f "%s"' % iso['iso_path']
            os.system(cmd_delete)
        delete_sql = "delete from platdeploy_manage where id = %s" % id
        db.execute(delete_sql)
        return HttpResponseRedirect(reverse('listplatmanagedeployurl'))
