#!/usr/bin/env python

import os
import sys
import argparse
import shutil

from kiwimasher.utils import ensure_dir, run_cmd, run_term_on_error, is_number


def build_file_list(subfolder=None):
    filelist = list()

    if subfolder:
        start_dir = os.path.join(dirpath, subfolder)
    else:
        start_dir = dirpath

    for root, dirs, filenames in os.walk(start_dir):
        for filename in filenames:
            path_full = os.path.join(root, filename)
            path_rel = os.path.relpath(path_full, start_dir)
            dir_path_full = os.path.dirname(path_full)
            dir_path_rel = os.path.relpath(dir_path_full, start_dir)
            if dir_path_rel == '.':
                dir_path_rel = ''
            basename, ext = os.path.splitext(filename)
            ext = ext[1:].lower()
            if args.sources and ext != args.sources:
                continue

            file_data = {
                'path_full': path_full,
                'path_rel': path_rel,
                'basename': basename,
                'ext': ext,
                'dir_path_full': dir_path_full,
                'dir_path_rel': dir_path_rel
            }

            filelist.append(file_data)
    return filelist


def get_target_path(file_obj, subfolder_str):
    if args.inplace:
        return f['path_full']

    if target_format.startswith('png'):
        target_ext = 'png'

    target_filename = '{basename}.{ext}'.format(basename=f['basename'], ext=target_ext)
    target_dir = os.path.join(dirpath, subfolder_str, f['dir_path_rel'])
    ensure_dir(target_dir)
    target_fullpath = os.path.join(target_dir, target_filename)
    return target_fullpath


def skip_if_date_equals(src_fullpath, target_fullpath):
    if not os.path.exists(target_fullpath):
        return False
    src_date = os.path.getmtime(src_fullpath)
    target_date = os.path.getmtime(target_fullpath)
    return src_date == target_date


def do_processing(file_obj):
    src_fullpath = file_obj['path_full']

    if not args.process:
        target_fullpath = get_target_path(file_obj, 'processed')
        if args.originals:
            shutil.copyfile(src_fullpath, target_fullpath)

    elif args.process[0] == 'resize_w':
        if len(args.process) != 2 or not is_number(args.process[1]):
            sys.exit('Wrong usage, use -p resize_w width')
        width = int(args.process[1])
        target_fullpath = get_target_path(file_obj, '{}x'.format(width))
        if skip_if_date_equals(src_fullpath, target_fullpath):
            return
        if args.skip and os.path.exists(target_fullpath):
            return
        cmd = 'convert "{src_fullpath}" -resize {width}x -quality 100 -sampling-factor 1x1 "{target_fullpath}"'.format(width=width, src_fullpath=src_fullpath, target_fullpath=target_fullpath)
        _, e, _ = run_cmd(cmd)
        if e:
            print e

    elif args.process[0] == 'resize_h':
        if len(args.process) != 2 or not is_number(args.process[1]):
            sys.exit('Wrong usage, use -p resize_h height')
        height = int(args.process[1])
        target_fullpath = get_target_path(file_obj, 'x{}'.format(height))
        if skip_if_date_equals(src_fullpath, target_fullpath):
            return
        if args.skip and os.path.exists(target_fullpath):
            return
        cmd = 'convert "{src_fullpath}" -resize x{height} -quality 100 -sampling-factor 1x1 "{target_fullpath}"'.format(height=height, src_fullpath=src_fullpath, target_fullpath=target_fullpath)
        _, e, _ = run_cmd(cmd)
        if e:
            print e

    elif args.process[0] == 'resize_inside':
        if len(args.process) != 3 or \
           not is_number(args.process[1]) or not is_number(args.process[2]):
            sys.exit('Wrong usage, use -p resize_smaller width height')
        width = int(args.process[1])
        height = int(args.process[2])
        suffix = '' if args.no_suffix else 'in'
        target_fullpath = get_target_path(file_obj, '{}x{}{}'.format(width, height, suffix))
        if skip_if_date_equals(src_fullpath, target_fullpath):
            return
        if args.skip and os.path.exists(target_fullpath):
            return
        cmd = 'convert "{src_fullpath}" -resize {width}x{height} -quality 100 -sampling-factor 1x1 "{target_fullpath}"'.format(height=height, width=width, src_fullpath=src_fullpath, target_fullpath=target_fullpath)
        _, e, _ = run_cmd(cmd)
        if e:
            print e

    elif args.process[0] == 'resize_outside':
        if len(args.process) != 3 or \
           not is_number(args.process[1]) or not is_number(args.process[2]):
            sys.exit('Wrong usage, use -p resize_outside width height')
        width = int(args.process[1])
        height = int(args.process[2])
        suffix = '' if args.no_suffix else 'out'
        target_fullpath = get_target_path(file_obj, '{}x{}{}'.format(width, height, suffix))
        if skip_if_date_equals(src_fullpath, target_fullpath):
            return
        if args.skip and os.path.exists(target_fullpath):
            return
        cmd = 'convert "{src_fullpath}" -resize {width}x{height}^ -quality 100 -sampling-factor 1x1 "{target_fullpath}"'.format(height=height, width=width, src_fullpath=src_fullpath, target_fullpath=target_fullpath)
        _, e, _ = run_cmd(cmd)
        if e:
            print e

    elif args.process[0] == 'resize_crop':
        if len(args.process) != 3 or \
           not is_number(args.process[1]) or not is_number(args.process[2]):
            sys.exit('Wrong usage, use -p resize_crop width height')
        width = int(args.process[1])
        height = int(args.process[2])
        suffix = '' if args.no_suffix else 'crop'
        target_fullpath = get_target_path(file_obj, '{}x{}{}'.format(width, height, suffix))
        if skip_if_date_equals(src_fullpath, target_fullpath):
            return
        if args.skip and os.path.exists(target_fullpath):
            return
        cmd = 'convert "{src_fullpath}" -resize {width}x{height}^ -gravity center -extent {width}x{height} -quality 100 -sampling-factor 1x1 "{target_fullpath}"'.format(height=height, width=width, src_fullpath=src_fullpath, target_fullpath=target_fullpath)
        _, e, _ = run_cmd(cmd)
        if e:
            print e

    elif args.process[0] == 'resize_fill':
        if len(args.process) != 3 or \
           not is_number(args.process[1]) or not is_number(args.process[2]):
            sys.exit('Wrong usage, use -p resize_fill width height')
        width = int(args.process[1])
        height = int(args.process[2])
        suffix = '' if args.no_suffix else 'fill'
        target_fullpath = get_target_path(file_obj, '{}x{}{}'.format(width, height, suffix))
        if skip_if_date_equals(src_fullpath, target_fullpath):
            return
        if args.skip and os.path.exists(target_fullpath):
            return
        cmd = 'convert "{src_fullpath}" -background none -resize {width}x{height} -gravity center -extent {width}x{height} -quality 100 -sampling-factor 1x1 "{target_fullpath}"'.format(height=height, width=width, src_fullpath=src_fullpath, target_fullpath=target_fullpath)
        _, e, _ = run_cmd(cmd)
        if e:
            print e

    else:
        sys.exit('Processing option not recognised: {}'.format(args.process[0]))

    return target_fullpath


parser = argparse.ArgumentParser()
parser.add_argument('-i', '--inplace', action='store_true', help='inplace process')
parser.add_argument('-o', '--originals', action='store_true', help='recursively process "originals"')
parser.add_argument('-t', '--target', choices=['png8'], help='target formats', required=True)
parser.add_argument('-s', '--sources', choices=['jpg', 'png'], help='source formats', required=True)
parser.add_argument('-p', '--process', nargs='+')
parser.add_argument('-c', '--level', default=1, type=int)
parser.add_argument('-v', '--verbose', action='store_true', help='verbose')
parser.add_argument('-l', '--list', action='store_true', help='list only')
parser.add_argument('--skip', action='store_true', help='skip existing images')
parser.add_argument('--no-suffix', action='store_true', help='don\'t append suffix to subfolders')

args = parser.parse_args()

dirpath = os.getcwd()
originals_str = 'originals'

if not args.inplace and not args.originals:
    sys.exit('Please choose either inplace (-i) or originals (-o)!')

if args.inplace:
    file_list = build_file_list()

if args.originals:
    file_list = build_file_list(originals_str)

if not file_list:
    sys.exit('No files found!')

target_format = args.target

for f in file_list:
    if args.list:
        print f['path_rel']
        continue

    orig_date = os.path.getmtime(f['path_full'])
    target_fullpath = do_processing(f)
    if not target_fullpath:
        continue

    print 'Processing: ' + f['path_rel']
    if args.verbose:
        print os.path.getsize(f['path_rel'])

    if args.level >= 1:

        if target_format == 'png8':
            pngquant_cmd = 'pngquant --ext .png -f --speed 1 "{}"'.format(target_fullpath)
            run_term_on_error(pngquant_cmd)
            if args.verbose:
                print os.path.getsize(target_fullpath)

            if args.level >= 2:
                advdef_cmd = 'advdef -z -4 -q "{}"'.format(target_fullpath)
                run_term_on_error(advdef_cmd)
                if args.verbose:
                    print os.path.getsize(target_fullpath)

    os.utime(target_fullpath, (orig_date, orig_date))



#     # if target_ext == 'jpg':
#     #     cmd = 'jpegoptim "{target_name}" -m85 --strip-all'.format(target_name=target_name)
#     #     _, e, _ = run_cmd(cmd)
#     #     if e:
#     #         print e

#
