import pickle
import os
import json
import codecs
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from tabulate import tabulate

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive',
          'https://www.googleapis.com/auth/drive.metadata',
          'https://www.googleapis.com/auth/drive.metadata.readonly']


def get_gdrive_service():
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)
    # return Google Drive API service
    return build('drive', 'v3', credentials=creds)


def main():
    """Shows basic usage of the Drive v3 API.
    Prints the names and ids of the first 5 files the user has access to.
    """
    service = get_gdrive_service()
    folder_id = "xxxxxxxxxxxxxxxx"  # teamdrive/folder id
    query = "'{}' in parents and trashed=false".format(folder_id)
    # Call the Drive v3 API
    results = service.files().list(
        supportsAllDrives=True,
        includeItemsFromAllDrives=True,
        pageSize=1000,
        q=query,
        fields="nextPageToken, files(id, name, mimeType, size, parents, modifiedTime, webViewLink, webContentLink)").execute()
    # get the results
    items = results.get('files', [])
    # simpan items ke json file
    with open('data.json', 'w', encoding='utf-8') as f:
        json.dump(items, f, ensure_ascii=False, indent=4)
    # list all 20 files & folders
    list_files(items)


def list_files(items):
    """given items returned by Google Drive API, prints them in a tabular way"""
    if not items:
        # empty drive
        print('No files found.')
    else:
        rows = []
        for item in items:
            # get the File ID
            id = item["id"]
            # get the name of file
            name = item["name"]
            try:
                # parent directory ID
                parents = item["parents"]
            except:
                # has no parrents
                parents = "N/A"
            try:
                # get the size in nice bytes format (KB, MB, etc.)
                size = get_size_format(int(item["size"]))
            except:
                # not a file, may be a folder
                size = "N/A"
            # get the Google Drive type of file
            mime_type = item["mimeType"]
            # get last modified date time
            modified_time = item["modifiedTime"]
            # ambil link view
            link_view = item["webViewLink"]
            # ambil download link
            try:
                # download link
                dl_link = item["webContentLink"]
            except:
                # bukan file
                dl_link = "Folder Bos"
            # append everything to the list
            rows.append((id, name, dl_link, parents, size,
                        mime_type, modified_time, link_view))
        print("Files:")
        # convert to a human readable table
        table = tabulate(rows, headers=["ID", "Name", "Download Link", "Parents",
                         "Size", "Type", "Modified Time", "Link View"], tablefmt="presto")
        # print the table
        print(table)
        # simpan table ke txt file
        with open('data.txt', 'w', encoding="utf-8") as f:
            f.write(table)


def get_size_format(b, factor=1024, suffix="B"):
    """
    Scale bytes to its proper byte format
    e.g:
        1253656 => '1.20MB'
        1253656678 => '1.17GB'
    """
    for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]:
        if b < factor:
            return f"{b:.2f}{unit}{suffix}"
        b /= factor
    return f"{b:.2f}Y{suffix}"


if __name__ == '__main__':
    main()
