

import paramiko
from ftplib import FTP
import os
import threading
import udp
import sys
import time
import stat
from PyQt5.QtCore import *

STR_RED="\033[1;31m"
STR_BLUE="\033[1;34m"
STR_END="\033[0m"




# 获得文件绝对路径
def getpath():
    path=os.path.abspath(sys.argv[0])
    list_str=path.split("\\")
    return path.replace(list_str[-1],"")



class myftp(QObject):
    local_path=getpath()+'file'
    # print(local_path)
    remot_path='/home/root'
    # 进度信号，ip，1~100
    rate_signal =pyqtSignal([str,int])
    # 结束信号，ip，成败，描述
    end_signal = pyqtSignal([str,bool,str])
    def __init__(self,ip,user,password):
        QObject.__init__(self)
        self.ip=ip
        self.ssh = paramiko.SSHClient()
        # 加入受信主机列表
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.ssh.connect(ip, 22, user, password,timeout=10)
        # 实例化一个 sftp对象,指定连接的通道
        self.sftp=self.ssh.open_sftp()
        self.invoke = self.ssh.invoke_shell()

    def send_cmd(self,cmd,inputs=[],sleep_s=0.5):
        # print("send cmd:",cmd)
        console=""
        input_list=[]
        input_list=inputs.copy()
        self.invoke.send(cmd+'\n') # \n很重要，相当于回车
        time.sleep(sleep_s)
        while True:
            out=self.invoke.recv(9999).decode("utf-8") # 提取数据然后解码
            if(len(out)>0):
                # print(out)
                console+=out
            else:
                break
            if(len(input_list)>0):
                send_str=input_list.pop(0)
                # print(self.ip,"|"+send_str)
                self.invoke.send(send_str+'\n')
                time.sleep(0.5)
            else:
                break
        console='\n'+console
        console=console.replace('\n','\n\t|')
        print(self.ip,console)
        # print("send cmd end")

    def get_file(self,path,src_list):
        lo_path=self.local_path+"\\"
        if(len(path)>0):
            lo_path=lo_path+path+"\\"
        if not os.path.exists(lo_path):
            os.makedirs(lo_path)
        for i in src_list:
            file_name=i.split('/')
            try:
                # print(file_name[-1])
                if(len(file_name[-1])>0):
                    self.sftp.get(remotepath=i, localpath=lo_path+file_name[-1])
                else:
                    file_list=self.scan_dir(i)
                    # self.sftp.get(remotepath=i, localpath=lo_path[0:-1])
                    self.get_file(path,file_list)
            except Exception as r:
                print(lo_path,"|"+str(r))
                print(STR_RED,lo_path,"|get ",i,"failed.",STR_END)
                return
            print(STR_BLUE,lo_path,"|get ",i,"success.",STR_END)
    def scan_dir(self,remotdir):
        # list=self.sftp.listdir(remotdir)
        attrs=self.sftp.listdir_attr(remotdir)
        file_list=[]
        for attr in attrs:
            if not stat.S_ISDIR(attr.st_mode):
                file_list.append(remotdir+attr.filename)
        # print(file_list)
        return file_list
        # 关闭连接
    def close(self):
        self.ssh.close()

    def put_cb(self,sent:int,all:int):
        # (sended*100/data.size()+((index-1)*100))/get_addrs().size()
        self.put_rate=sent*100//all
        rate=(self.put_rate+(self.index)*100)//self.len_files
        self.rate_signal.emit(self.ip,rate)
        # print("sent={d1},all={d2}".format(d1=sent,d2=all))
        # print("rate=",rate)

    # 添加进度和结束信号，供qt显示
    def put_file(self,prefix,dst_list,src_list):
        if not os.path.exists(self.local_path):
            self.end_signal.emit(self.ip,False,"local path is not exists.")
            return
        self.len_files=len(dst_list)
        self.index=0
        for i in dst_list:
            self.put_rate=0
            file_name=i.split('/')
            temp_path=self.remot_path+'/'+file_name[-1]
            src_path=""
            if(len(src_list)==0):
                src_path=self.local_path+'\\'+file_name[-1]
            else:
                src_path=src_list[self.index]
            if os.path.exists(src_path):

                self.send_cmd("rm "+i,sleep_s=2)
                # self.sftp.chmod(i.replace(file_name[-1],""),777)
                self.send_cmd("chmod "+"777 "+i.replace(file_name[-1],""),sleep_s=2)
                try:
                    self.sftp.put(localpath=src_path, remotepath=i,callback=self.put_cb)
                except Exception as r:
                    print(prefix,"|"+str(r))
                    print(STR_RED,prefix,"|put ",i,"failed.",STR_END)
                    self.end_signal.emit(self.ip,False,str(r)+"|"+i)
                    return
                self.index+=1
                print(STR_BLUE,prefix,"|put ",i,"success.",STR_END)
                # self.sftp.chmod(i,777)
                self.send_cmd("chmod "+"777 "+i)
                # self.rate_signal.emit(self.ip,self.index*100//self.len_files)
            else:
                print(STR_RED,prefix,"|file:"+src_path +" not exist.",STR_END)
                self.end_signal.emit(self.ip,False,"file:"+src_path +" not exist.")
                return
        self.end_signal.emit(self.ip,True,"success")








# 从虚拟机下载文件
def load_file(ip,src_list):
    print("load file from:",ip)
    # ftp=myftp(ip,"andy","123456")
    ftp=myftp(ip,"bitman","123456")
    ftp.get_file("",src_list)
    ftp.close()
    print("load file end.")


# 保存文件到开发板
def save_file(ip,restart:bool,dst_list,src_list):
    try:
        ftp=myftp(ip,"root","")
        if(restart==True):
            print(ip,"|stop app.")
            ftp.send_cmd("systemctl stop atk-qtapp-start.service")
        ftp.put_file(ip,dst_list,src_list)
        if(restart==True):
            print(ip,"|start app.")
            ftp.send_cmd("systemctl restart atk-qtapp-start.service")
        ftp.send_cmd("sync")
        ftp.close()
        # print(ip,"|save file end.")
    except Exception as r:
        print(STR_RED,ip,"|"+str(r),STR_END)


# 从开发板加载文件
def get_file(ip,path,get_list):
    # print("load file from:",ip)
    ftp=myftp(ip,"root","")
    ftp.get_file(path,get_list)
    ftp.close()
    # print("load file end.")

def send_cmd(ip,cmd_list):
    ftp=myftp(ip,"root","")
    for i in cmd_list:
        ftp.send_cmd(i[0],i[1])
    ftp.close()





# 定义要从虚拟机下载的文件
src_list=[]
# src_list.append("/home/bitman/linux/nfs/stm32mp157d-atk.dtb")
# src_list.append("/home/bitman/linux/nfs/QDesktop-fb")
# src_list.append("/home/bitman/QtWorkSpace/tcp_tr_can/checker_ye_cfg08.json")
src_list.append("/home/bitman/linux/nfs/")

# 定义要保存到开发板的文件
dst_list=[]
# 第一次拷贝设备树会因为权限问题不能运行
# dst_list.append("/run/media/mmcblk2p2/stm32mp157d-atk.dtb")
# dst_list.append("/usr/local/QDesktop-fb")
# dst_list.append("/home/root/config/checker_app_pre.sh")
# dst_list.append("/home/root/config/cfg.json")
# dst_list.append("/home/root/config/checker_ye_cfg11.json")
dst_list.append("/home/root/config/judge.lua")
# dst_list.append("/home/root/config/JQChecker_0008.bin")


# 定义要从开发板获取的文件
get_list=[]
# get_list.append("/home/root/comm_log/comm_log.csv")
# get_list.append("/home/root/log/debug_log.txt")
# get_list.append("/home/root/config/checker_app_pre.sh")
# get_list.append("/home/root/config/cfg.json")
# get_list.append("/home/root/config/judge.lua")
get_list.append("/home/root/comm_log/")

# 定义命令

cmd_list=[]
# cmd_list.append(("/usr/sbin/useradd -d / -g wheel andy",[]))
# cmd_list.append(("passwd andy",["123456","123456"]))
cmd_list.append(("rm ~/config/checker_app_pre.sh",[]))
# cmd_list.append(("ls ~/config/",[]))
# cmd_list.append(("ls /usr/local/",[]))



# 自动扫描从机地址，然后升级文件

# python .\ftp.py get 从开发板下载文件
# python .\ftp.py save 保存文件到开发板
# python .\ftp.py cmd 发送命令列表

def run():
    if(len(sys.argv)<2):
        print("argv too less")
        return
    print(sys.argv[0])
    cmd=sys.argv[1]

    ip_list=[]
    u=udp.myudp(1,255)
    u.find("192.168.80")
    ip_list=u.dst_ip_list
    if(len(ip_list)==0):
        # ip_list.append(("192.168.80.120","local_id_1"))
        ip_list.append(("192.168.80.81","local_id_1"))
        ip_list.append(("192.168.80.82","local_id_2"))
        ip_list.append(("192.168.80.83","local_id_3"))
        ip_list.append(("192.168.80.84","local_id_4"))
        ip_list.append(("192.168.80.85","local_id_5"))
        ip_list.append(("192.168.80.86","local_id_6"))
        ip_list.append(("192.168.80.87","local_id_7"))
        ip_list.append(("192.168.80.88","local_id_8"))
    print("find ip_list as:")
    print(ip_list)
    threads = []
    
    if(cmd=="save"):
        # load_file("192.168.80.188",src_list)
        print('put file to ip_list.')
        for i in ip_list:
            t = threading.Thread(target=save_file, args=(i[0],True,dst_list ))
            threads.append(t)
            t.start()
    elif(cmd=="get"):
        print("get file from ip_list.")
        for i in ip_list:
            t = threading.Thread(target=get_file, args=(i[0],i[1],get_list ))
            threads.append(t)
            t.start()
    elif(cmd=="cmd"):
        print("send cmd to ip_list")
        for i in ip_list:
            t = threading.Thread(target=send_cmd, args=(i[0],cmd_list ))
            threads.append(t)
            t.start()
    elif(cmd=="load"):
        load_file("192.168.80.188",src_list)
    #等待所有线程任务结束。
    for t in threads:
        t.join()
    
    print("all task were end.")



if __name__ == "__main__":
    run()
