# -*- coding: utf-8 -*-

import os
import sys
import shutil
import datetime
import copy
import time

class FilePage(dict):
    """
    docstring for FilePage
    """
    def __init__(self, *args,**keys):
        """
        如果传入字典，那么我们会将字典更新到本类
        如果你指定了 _filename 的键值，那么我们会取你这个键值作为 self[name] 变量
        """
        #t0 = time.time()
        manager = BaseFileManager()
        self._filename = "name"
        self._path = "path"
        if isinstance(args[0],dict):
            self.update(args[0])
        if self._filename in self:    #检查是否已经赋值到dict
            self[self._filename] = manager.getFileName(self[self._filename])
        if self._filename in keys:    #检查一下是否在keys 字典
            self[self._filename] = manager.getFileName(keys.pop(self._filename))
        else:
            if not self._filename in args[0]:
                raise FileNotFoundError("Not Input Name for FIlePage") #找不到你的名字,哪怕我想记住你,但是似乎根本接触不到!
        #if os.path.isabs(args[0][self._filename]):
        #    self[self._path] = args[0][self._filename]
        #else:
        #    self[self._path] = manager.pathToURL(os.path.abspath(args[0][self._filename]))
        self.update(keys)    #用字典作为您自定义的值，你可以自定义任何值，但是不建议这样做


    def toString(self):
        return repr(self)
        
    def check(self):
        return BaseFileManager().check(self[self._filename])

    

        

class BaseFileManager(object):
    """
    基础类，有各种基础功能
    """

    def check(self,path):
        if not os.path.exists(path):
            return -1
        if os.path.isdir(path):
            return 0
        else:
            return 1

    def delete (self,path):
        if self.check(path) == 0:
            shutil.rmtree(path)
            return True
        if self.check(path) == 1:
            os.remove(path)
            return True
        else:
            return False

        
    def move(self,oldPath,newPath):
        if self.check(newPath) != 1:
            if self.check(oldPath) == -1:
                return False
            if oldPath == newPath:
                return True
            shutil.move(oldPath,newPath)
            return True
        else:
            return False
            
        
    def copy(self,oldPath,tarPath):
        if self.check(tarPath) != -1:
            self.remove(tarPath)
            return True
        if self.check(oldPath) == 0:
            shutil.copytree(oldPath,tarPath)
            return True
        if self.check(oldPath) == 1:                                                 
            shutil.copy(oldPath,tarPath)
            return True
        return False

    def getFileName(self,filepath):
        """ 从文件路径里面分割出文件名，不论是绝对路径还是相对路径 """
        return os.path.split(filepath)[1]


    def getFilePath(self,filepath):
        """ 从文件路径里面分割出路径，不论是绝对路径还是相对路径 """
        return os.path.split(filepath)[0]


    def getDirLen(self,path="."):
        """ 获取目录下文件数量 """
        if path is "" or path is "./" or path is "/":
            path = "."
        if self.check(path) == 0:
            return len(os.listdir(path))
        return False


    def getFileInfo(self,filename,Dateformat=True,formatString="%Y-%m-%d %H:%M:%S"):
        """
        只能获取一个文件的信息
        Dateformat 是否时间进行数据格式化 ,默认 True
        formatString 时间格式化字符串，默认 %Y-%m-%d %H:%M:%S
        -------------------------------------
        return 返回一个FilePage 有如下内容：
            size 大小 dir 是否目录 
            atime 数据的最后访问时间 
            mtime 数据的最后修改时间 
            ctime 节点最后更改时间
            name 文件名
            path 绝对路径
        
        """
        def __dateTimeF(dataF):
            tt = datetime.datetime.fromtimestamp(dataF)
            return tt.strftime(formatString) # 这是个时间格式化字符串，只能返回年份。更多使用方法参见手册。
        filename = self.toAbsPath(filename)
        info = {}
        if not os.path.exists(filename):
            return False
        data = os.stat(filename)
        #atime = data.st_atime
        mtime = data.st_mtime
        #ctime = data.st_ctime
        #info["chmod"] = os.chmod(filename)
        if Dateformat:
           # atime = __dateTimeF(atime)    #调用上面封装的函数
            mtime = __dateTimeF(mtime)
           # ctime = __dateTimeF(ctime)
        info["size"] = data.st_size
        info["dir"] = os.path.isdir(filename)
        #info["atime"] = atime
        info["mtime"] = mtime
        #info["ctime"] = ctime
        info["name"] = filename
        #stat.st_atime #（数据的最后访问时间）
        #stat.st_mtime #（数据的最后修改时间）
        #stat.st_ctime #（创建时间）
        return FilePage(info)


    def getDirList(self,path=None,onlyFileName=True):
        """ 获取任意目录下的任何文件 """
        if path == None:
            path = "."
        path = self.toAbsPath(path)
        if self.check(path) == 0:
            li = list(os.listdir(path))
            if onlyFileName:
                return li
            ww = []
            ww = self.addDir(li,path)
            # for v in li:
            #     ww.append(path + "/" + v)
            return ww
        return []

    def getDirLength(self,path):
        if self.check(path) == 0:
            return len(self.getDirList(path))
        return -1

    def pathToURL(self,path):
        return path.replace("\\","/").replace('//','/')

    def urlToPath(self,path):
        return path.replace("/","\\")

    def toAbsPath(self,path):
        path = path.replace("\\","/")
        if os.path.isabs(path):
            return path
        return os.path.abspath(path).replace("\\","/") 

    def addDir(self,listpath,addDir):
        """ 为列表的每一项加入一个前置目录，有时候使用某些跨目录函数的时候会需要这个功能"""
        if not isinstance(list,list):
            listpath = list(listpath)
        for i,v in enumerate(listpath[:]):
            listpath[i] = addDir + "/" + v
        return listpath





class FileManager(BaseFileManager):
    """
    高级文件管理类，在BaseFileManager的基础上代码复用，递归反复使用
    """
    def __init__(self):
        return

    def postList(self,*args,**keys):
        """ 列表矩阵倒转算法,你可以用它传递任何多元列表作为参数，甚至可以传递任何keys作为参数"""
        #t0 = time.time()
        
        fun = keys.pop("func")
        if not isinstance(args[0],list):
            #例如: FunctionMove ("Hell.in","OOW.txt")
            #li = [args]
            #print("命中")
            return fun(*args,**keys)
        else:
            li = args
        returntmp = []
        tmp=[]
        for i in range(0,len(args[0])):
            for v in args:
                tmp.append(v[i])
            #print('传进执行函数的参数是: ',str(tmp))
            rbool = fun(*tmp,**keys)
            tmp.clear()
            if rbool: 
                returntmp.append(rbool); #返回值
        #t1 = time.time()
        #print ("矩阵倒置 %s: %s seconds" %
        #('Speed:',str(t1-t0))
        #)
        return returntmp
    def getFileNames(self,pathlist):
        """ 从文件路径里面分割出文件名，不论是绝对路径还是相对路径 可多操作，返回列表"""
        tmp = []
        for v in pathlist:
            tmp.append(os.path.split(v)[1])
        return tmp

    def deletes(self,pathlist):
        return self.postList(pathlist,func=self.delete)

        
    def moves(self,oldPath,newPath):
        return self.postList(oldPath,newPath,func=self.move)
        
        
    def copys(self,oldPath,newPath):
        return self.postList(oldPath,newPath,func=self.copy)

    def getFileInfos(self,filename):
        """
        获取列表文件的信息，返回列表，其中有FilePage组成的包
        -------------------------------------
        return FilePage
            [FileP,FileP2,FileP3]
        """
        li = self.postList(filename,func=self.getFileInfo)
        return li


    def getDirLists(self,path=None,onlyFileName=True):
        """ 获取任意目录下的任何文件 """
        return self.postList(path,onlyFileName=onlyFileName,func=self.getDirList)

    
    def getDirListFileALL(self,dst=None):
        """
        一次性获取目录下所有文件的所有信息
        -------------------------------------
        return 
            返回{page1,page2,...}
        """
        #print("获取列表",dst)
        #if isinstance(dst,list):
        #    dirlist = []
        #    for listname in dst:
        #        tmp = self.getDirListFileALL(listname)
        #        if tmp:
        #            dirlist.append(tmp) #递归
        #    return dirlist
        #单个
        dst = self.toAbsPath(dst)
        if not os.path.lexists(dst):
            return False
        if not os.path.isdir(dst):
             return self.getFileInfo(dst)        
        dirlist = self.getDirList(dst)
        dirlist = self.addDir(dirlist,dst)
        tmp =  self.getFileInfos(dirlist)
        tmp.insert(0,dst); #第一个元素为路径
        return tmp;

        

    def dirTree(self,path,funback):  
        """ 
        利用反馈函数来进行某些操作
        -------------------------------------
        funback 您的反馈函数，线程会为每一个元素调用您的函数值，函数应该是fun(name)的。
        ------------------------------------------------------
        警告：切记函数花费的时间可能会超过您的预期
        """
        for root,dirs,files in os.walk(path):  #将os.walk在元素中提取的值，分别放到root（根目录），dirs（目录名），files（文件名）中。  
            for file in files:  
                funback(os.path.join(root,file))   #根目录与文件名组合，形成绝对路径。 

    def FindFile(self,path,filename,fast=False,matching=False):
        """
        在指定目录下寻找文件
        filename 文件名
        Fast 是否只需要寻找到第一个，注意这个寻找顺序是随机排列的
        matching 是否匹配查找，只要有关键字的将加入列表，可以配合Fast只配合一个
        -------------------------------------
        return 
            返回一个绝对路径的完整路径，包括文件名列表
            如果使用了fast，则返回一个单独的str
            如果未找到返回False
        ------------------------------------------------------
        警告：切记函数花费的时间可能会超过您的预期
        """
        li = []
        for root,dirs,files in os.walk(path):
            for file in files:  
                if matching:
                    for v in list(filename):
                        if v in file:
                            if fast:
                                return os.path.join(root,file)
                            li.append(os.path.join(root,file))
                else:
                    for v in list(filename):
                        if file == v:
                            if fast:
                                return os.path.join(root,file)
                            li.append(os.path.join(root,file))
        if len(li) <= 0:
            return False;            
        return list(set(li))


#貌似只要有s的，都会返回一个列表，里面显示结果
if __name__ == "__main__":
    www = FileManager()
    print(www.getDirList("1",False))
    print(www.getDirList("D:/[0000]Suwings/Python/Bottle/Model/minedir/1/minedata",False))


    print(www.getDirLists(["D:/[0000]Suwings/Python/Bottle/Model/minedir/1"],onlyFileName=False))
    #print(www.deletes(www.getDirLists(["1"],onlyFileName=False)))

    print(www.getFileInfos(["./SwFiles.py","1"]))

    print("======File P=========")
    name = "../../Bottle.py"
    e = www.getFileInfo(name)
    e.update({"name":name})
    print("原先:",str(e))
    w = FilePage(e)
    print("类化:",w.toString() ," ")
    for k,v in w.items():
        print("找到 ",k,"->",v)
    #print(www.moves(["9.txt","wswws.txt"],["98.txt","yy.txt"]))
    print("-----------------getFileInfos - 多 ----------------------")
    p = www.getFileInfos(["swfile.py","SwFiles.py","SwFiles - Copy"])
    print(p)
    print("-----------------getFileInfos - 单 ----------------------")
    we = www.getFileInfo("SwFiles.py")
    print("类化:")
    for k,v in we.items():
        print("找到 ",k,"->",v)
    print("-----------------getDirFileInfos----------------------")
    p = www.getDirListFileALL(www.getDirList("D:\[0000]Suwings\Python\Bottle\Model\minedir"))
    print(type(p[1][0]) )
    z = www.getDirListFileALL("minedata")
    print(z)
    print("-----------------getDirFileInfos - 单 ----------------------")
    p = www.getFileInfo("minedata")
    print(p.toString())
    print(str(we))
    print("类化:")
    for k,v in we.items():
        print("找到 ",k,"->",v)
    print("-----------------getDirFileInfos 获取目录下的所有文件----------------------")
    p = www.getDirListFileALL(www.getDirList("D:\[0000]Suwings\Python\Bottle\Model\minedir"))
    print(str(p) )
    z = www.getDirListFileALL("1")
    print(z)

    print("-----------------getDirFileInfos - 单 ----------------------")
    p = www.getFileInfo("wcaocopy")
    print(str(p))

    print("-----------------www.getDirList(D:\[0000]Suwings\Python\Bottle\Model\minedir) - 单 ----------------------")
    print(www.getDirList("D:\[0000]Suwings\Python\Bottle\Model\minedir"))
