#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Description: Do the Plex Dance!
Author: Blacktwin, SwiftPanda16
Requires: plexapi, requests

Original Dance moves
    1. Move all files for the media item out of the directory your Library is looking at,
        so Plex will not “see” it anymore
    2. Scan the library (to detect changes)
    3. Empty trash
    4. Clean bundles
    5. Double check naming schema and move files back
    6. Scan the library

https://forums.plex.tv/t/the-plex-dance/197064

Script Dance moves
    1. Create .plexignore file in affected items library root
        .plexignore will contain:

         # Ignoring below file for Plex Dance
         *Item_Root/*

        - if .plexignore file already exists in library root, append contents
    2. Scan the library
    3. Empty trash
    4. Clean bundles
    5. Remove or restore .plexignore
    6. Scan the library
    7. Optimize DB

 Example:
     Dance with rating key 110645
        plex_dance.py --ratingKey 110645
    
    From Unraid host OS
        plex_dance.py --ratingKey 110645 --path /mnt/user

    *Dancing only works with Show or Movie rating keys
    
 **After Dancing, if you use Tautulli the rating key of the dancing item will have changed.
    Please use this script to update your Tautulli database with the new rating key
        https://gist.github.com/JonnyWong16/f554f407832076919dc6864a78432db2
"""
from __future__ import print_function
from __future__ import unicode_literals

from plexapi.server import PlexServer
from plexapi.server import CONFIG
import requests
import argparse
import time
import os

# Using CONFIG file
PLEX_URL = ''
PLEX_TOKEN = ''

IGNORE_FILE = "# Ignoring below file for Plex Dance\n{}"

if not PLEX_TOKEN:
    PLEX_TOKEN = CONFIG.data['auth'].get('server_token')
if not PLEX_URL:
    PLEX_URL = CONFIG.data['auth'].get('server_baseurl')

session = requests.Session()
# Ignore verifying the SSL certificate
session.verify = False  # '/path/to/certfile'
# If verify is set to a path to a directory,
# the directory must have been processed using the c_rehash utility supplied
# with OpenSSL.
if session.verify is False:
    # Disable the warning that the request is insecure, we know that...
    import urllib3

    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

plex = PlexServer(PLEX_URL, PLEX_TOKEN, session=session)


def section_path(section, filepath):
    for location in section.locations:
        if filepath.startswith(location):
            return location


def refresh_section(sectionID):
    plex = PlexServer(PLEX_URL, PLEX_TOKEN, session=session)
    section = plex.library.sectionByID(sectionID)
    section.update()
    time.sleep(10)
    plex = PlexServer(PLEX_URL, PLEX_TOKEN, session=session)
    section = plex.library.sectionByID(sectionID)
    while section.refreshing is True:
        time.sleep(10)
        print("Waiting for library to finish refreshing to continue dance.")
        plex = PlexServer(PLEX_URL, PLEX_TOKEN, session=session)
        section = plex.library.sectionByID(sectionID)


if __name__ == '__main__':

    parser = argparse.ArgumentParser(description="Do the Plex Dance!",
                                     formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument('--ratingKey', nargs="?", type=int, required=True,
                        help='Rating key of item that needs to dance.')
    parser.add_argument('--path', nargs="?", type=str,
                        help='Prefix path for libraries behind mount points.\n'
                             'Example: /mnt/user Resolves: /mnt/user/library_root')

    opts = parser.parse_args()

    item = plex.fetchItem(opts.ratingKey)
    item.reload()
    sectionID = item.librarySectionID
    section = plex.library.sectionByID(sectionID)
    old_plexignore = ''

    if item.type == 'movie':
        item_file = item.media[0].parts[0].file
        locations = os.path.split(item.locations[0])
        item_root = os.path.split(locations[0])[1]
        library_root = section_path(section, locations[0])
    elif item.type == 'show':
        locations = os.path.split(item.locations[0])
        item_root = locations[1]
        library_root = section_path(section, locations[0])
    else:
        print("Media type not supported.")
        exit()

    library_root = opts.path + library_root if opts.path else library_root
    plexignore = IGNORE_FILE.format('*' + item_root + '/*')
    item_ignore = os.path.join(library_root, '.plexignore')
    # Check for existing .plexignore file in library root
    if os.path.exists(item_ignore):
        # If file exists append new ignore params and store old params
        with open(item_ignore, 'a+') as old_file:
            old_plexignore = old_file.readlines()
            old_file.write('\n' + plexignore)

    # 1. Create .plexignore file
    print("Creating .plexignore file for dancing.")
    with open(item_ignore, 'w') as f:
        f.write(plexignore)
    # 2. Scan library
    print("Refreshing library of dancing item.")
    refresh_section(sectionID)
    # 3. Empty library trash
    print("Emptying Trash from library.")
    section.emptyTrash()
    time.sleep(5)
    # 4. Clean library bundles
    print("Cleaning Bundles from library.")
    plex.library.cleanBundles()
    time.sleep(5)
    # 5. Remove or restore .plexignore
    if old_plexignore:
        print("Replacing new .plexignore with old .plexignore.")
        with open(item_ignore, 'w') as new_file:
            new_file.writelines(old_plexignore)
    else:
        print("Removing .plexignore file from dancing directory.")
        os.remove(item_ignore)
    # 6. Scan library
    print("Refreshing library of dancing item.")
    refresh_section(sectionID)
    # 7. Optimize DB
    print("Optimizing library database.")
    plex.library.optimize()