import os
import platform
import requests
import time


def build_ebsynth():
    if os.path.exists('deps/ebsynth/bin/ebsynth'):
        print('Ebsynth has been built.')
        return

    os_str = platform.system()

    if os_str == 'Windows':
        print('Build Ebsynth Windows 64 bit.',
              'If you want to build for 32 bit, please modify install.py.')
        cmd = '.\\build-win64-cpu+cuda.bat'
        exe_file = 'deps/ebsynth/bin/ebsynth.exe'
    elif os_str == 'Linux':
        cmd = 'bash build-linux-cpu+cuda.sh'
        exe_file = 'deps/ebsynth/bin/ebsynth'
    elif os_str == 'Darwin':
        cmd = 'sh build-macos-cpu_only.sh'
        exe_file = 'deps/ebsynth/bin/ebsynth.app'
    else:
        print('Cannot recognize OS. Ebsynth installation stopped.')
        return

    os.chdir('deps/ebsynth')
    print(cmd)
    os.system(cmd)
    os.chdir('../..')
    if os.path.exists(exe_file):
        print('Ebsynth installed successfully.')
    else:
        print('Failed to install Ebsynth.')


def download(url, dir, name=None, chunk_size=67108864, max_retries=12, retry_delay=5):
    os.makedirs(dir, exist_ok=True)
    if name is None:
        name = url.split('/')[-1]
    path = os.path.join(dir, name)
    
    retries = 0
    while retries <= max_retries:
        try:
            if not os.path.exists(path):
                print(f'Downloading {name} ...', end='\r')
                response = requests.get(url, stream=True)
                response.raise_for_status()  # Raise an exception if the request failed
                total_length = int(response.headers.get('content-length', 0))
                
                downloaded = 0
                start_time = time.time()
                with open(path, 'wb') as file:
                    for chunk in response.iter_content(chunk_size=chunk_size):
                        downloaded += len(chunk)
                        file.write(chunk)
                        
                        # Check if a second has passed since the last update
                        elapsed_time = time.time() - start_time
                        if elapsed_time >= 1.0:
                            start_time = time.time()
                            print(f"{name} \t {downloaded}/{total_length} bytes ({100 * downloaded / total_length:.2f}%)", end='\r')
                print('Download successfully.', ' ' * 50)  # Clearing the previous line with spaces
                return
        except Exception as e:
            retries += 1
            if retries > max_retries:
                raise e
            print(f"Error occurred while downloading: {e}. Retrying in {retry_delay} seconds...", end='\r')
            time.sleep(retry_delay)


		
def download_models(url, save_path, max_retries=3, retry_delay=5):
    retries = 0
    while retries <= max_retries:
        try:
            response = requests.get(url[0], stream=True)
            response.raise_for_status()  # Raise an exception if the request failed
            
            # Get the total content length
            total_length = int(response.headers.get('content-length', 0))
            
            os.makedirs(save_path, exist_ok=True)  # Create the directory if it doesn't exist
            with open(os.path.join(save_path, url[1]), 'wb') as file:
                downloaded = 0
                start_time = time.time()
                for chunk in response.iter_content(chunk_size=67108864):
                    downloaded += len(chunk)
                    file.write(chunk)
                    
                    # Check if a second has passed since the last update
                    elapsed_time = time.time() - start_time
                    if elapsed_time >= 1.0:
                        start_time = time.time()
                        print(f"{url[1]} \t {downloaded}/{total_length} bytes ({100 * downloaded / total_length:.2f}%)", end='\r')
            print('Download successfully.', ' ' * 50)  # Clearing the previous line with spaces
            return
        except Exception as e:
            retries += 1
            if retries > max_retries:
                raise e
            print(f"Error occurred while downloading: {e}. Retrying in {retry_delay} seconds...", end='\r')
            time.sleep(retry_delay)




def download_file(url, path,filename, retries=9, timeout=120):
    """
    Download a file from a given URL and save it to the specified path with resume support.
    
    Parameters:
    - url (str): URL of the file to be downloaded.
    - path (str): Directory where the file will be saved.
    - retries (int): Number of retries if the download fails. Default is 3.
    - timeout (int): Timeout for the download request in seconds. Default is 10.
    """
    
    # Determine the file name from the URL or content disposition
    response = requests.head(url, allow_redirects=True)
    content_disposition = response.headers.get('content-disposition')
    print(f"\nDownloading {filename}!")
    file_path = os.path.join(path, filename)
    
    downloaded_size = 0
    if os.path.exists(file_path):
        downloaded_size = os.path.getsize(file_path)
    
    headers = {}
    if downloaded_size:
        headers['Range'] = f"bytes={downloaded_size}-"
    
    try:
        response = requests.get(url, headers=headers, stream=True, timeout=timeout)
        response.raise_for_status()
        
        total_size = downloaded_size + int(response.headers.get('content-length', 0))
        
        block_size = 2048576  # 1 MB
        
        with open(file_path, 'ab') as file:
            start_time = time.time()
            for data in response.iter_content(block_size):
                file.write(data)
                
                downloaded_size += len(data)
                elapsed_time = time.time() - start_time
                download_speed = downloaded_size / elapsed_time / 1024  # Speed in KiB/s
                
                # Display download progress and speed
                progress = (downloaded_size / total_size) * 100
                print(f"Downloaded {downloaded_size}/{total_size} bytes "
                      f"({progress:.2f}%) at {download_speed:.2f} KiB/s", end='\r')
        
        print(f"\nDownload completed {filename}!")
        return file_path

    except requests.RequestException as e:
        if retries > 0:
            print(f"Error occurred: {e}. Retrying...")
            return download_file(url, path, retries=retries-1, timeout=timeout)
        else:
            print("Download failed after multiple retries.")
            return None

# Example usage:
# download_file('https://example.com/file.zip', '/path/to/save')

import os

# Directory path
dir_name = "models"

# Create directory if it doesn't exist
if not os.path.exists(dir_name):
    os.makedirs(dir_name)
    print(f"'{dir_name}' directory created.")
else:
    print(f"'{dir_name}' directory already exists.")


download_file('https://huggingface.co/lllyasviel/ControlNet/resolve/main/models/control_sd15_canny.pth','models','control_sd15_canny.pth')
download_file('https://huggingface.co/lllyasviel/ControlNet/resolve/main/models/control_sd15_hed.pth','models','control_sd15_hed.pth')
download_file('https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned.safetensors','models','Stable_Diffusion_1.5.safetensors')
download_file('https://civitai.com/api/download/models/130072?type=Model&format=SafeTensor&size=full&fp=fp16','models','Realistic_Vision_V5.1.safetensors')
download_file('https://civitai.com/api/download/models/103436?type=Model&format=SafeTensor&size=full&fp=fp32','models','Flat_2D_Animerge.safetensors')
download_file('https://huggingface.co/PKUWilliamYang/Rerender/resolve/main/models/gmflow_sintel-0c07dcb3.pth','models','gmflow_sintel-0c07dcb3.pth')
download_file('https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.ckpt','models','vae-ft-mse-840000-ema-pruned.ckpt')
download_file('https://civitai.com/api/download/models/46846','models','ReV_Animated_122.safetensors')

#build_ebsynth() uncomment this and build it if you want manually
