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

# Copyright (C) 2015 Martin Wimpress <code@ubuntu-mate.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

import os
import subprocess
import shutil
import sys
import tempfile
from gi.repository import Gio
from subprocess import PIPE


def autostop(filename):
    desktopfile = os.path.join('/','etc','xdg','autostart', filename)
    if os.path.exists(desktopfile):
        os.remove(desktopfile)


def install_layout(filename):
    if os.path.exists(os.path.join(tempfile.gettempdir(),filename)):
        shutil.copy2(os.path.join(tempfile.gettempdir(),filename),
                     os.path.join('/','usr','share','mate-panel','layouts',filename))
        os.remove(os.path.join(tempfile.gettempdir(),filename))
    else:
        # If a .dock hint is not found but is installed, remove it.
        if filename.endswith('dock') and os.path.exists(os.path.join('/','usr','share','mate-panel','layouts',filename)):
            os.remove(os.path.join('/','usr','share','mate-panel','layouts',filename))
        print('Unable to find ' + os.path.join(tempfile.gettempdir(),filename))


def delete_layout(filename):
    if 'tweak' in filename:
        layout = os.path.join('/','usr','share','mate-panel','layouts',filename)
        if os.path.exists(layout):
            os.remove(layout)
        else:
            print('Unable to find ' + layout)
    else:
        print('WARNING! I will only delete custom layouts. Skipping ' + layout)


def backup_layout(filename):
    VALID = {'toplevel': ('expand', 'size', 'orientation'),
             'launcher': ('object-type', 'launcher-location', 'menu-path', 'toplevel-id', 'position', 'panel-right-stick', 'locked'),
             'applet': ('object-type', 'applet-iid', 'toplevel-id', 'position', 'panel-right-stick', 'locked'),
             'drawer': ('object-type', 'attached-toplevel-id', 'toplvel-id', 'position', 'panel-right-stick', 'use-custom-icon'),
             'menu-bar': ('object-type', 'applet-iid', 'toplevel-id', 'position', 'panel-right-stick', 'locked'),
             'menu': ('object-type', 'toplevel-id', 'position', 'panel-right-stick', 'locked'),
             'action': ('object-type', 'action-type', 'position', 'toplevel-id', 'panel-right-stick', 'locked'),
             'separator': ('object-type', 'toplevel-id', 'position', 'panel-right-stick', 'locked')}

    schemas = {'panel': 'org.mate.panel',
               'object': 'org.mate.panel.object',
               'toplevel':'org.mate.panel.toplevel'}

    paths = {'object': '/org/mate/panel/objects/',
             'toplevel': '/org/mate/panel/toplevels/'}

    general_settings = Gio.Settings.new(schemas['panel'])

    toplevel_ids = general_settings['toplevel-id-list']
    object_ids = general_settings['object-id-list']

    layout = []

    for toplevel in toplevel_ids:
        settings = Gio.Settings.new_with_path(
            schemas['toplevel'],
            paths['toplevel'] + toplevel + '/')

        layout.append("[Toplevel %s]\n" % toplevel)

        for key in settings.keys():
            val = settings[key]
            if str(val) == "True" or str(val) == "False":
                val = str(val).lower()

            if key in VALID['toplevel']:
                layout.append("%s=%s\n" % (key, val))
        layout.append("\n")

    for obj in object_ids:
        settings = Gio.Settings.new_with_path(
            schemas['object'],
            paths['object'] + obj + '/')

        obj_toplevel = settings['toplevel-id']
        obj_type = settings['object-type']
        obj_name = ""
        if obj_type == "applet":
            obj_name = settings['applet-iid'].split(":")[-1]
        elif obj_type == "action":
            obj_name = settings['action-type']
        else:
            obj_name = obj_type

        if not obj_toplevel in toplevel_ids:
            print("WARNING! object \"%s\" references unknown toplevel... skipped" % obj_name)
            continue

        layout.append("[Object %s]\n" % obj_name.lower())
        for key in settings.keys():
            if key in VALID[obj_type]:
                val = settings[key]
                if str(val) == "True" or str(val) == "False":
                    val = str(val).lower()

                layout.append("%s=%s\n" % (key, val))
        layout.append("\n")

        layout.extend(get_non_panel_settings())

    #print(layout)
    with open(os.path.join(tempfile.gettempdir(), filename + '.layout'), 'w') as f:
        f.writelines(layout)

    # Dump dconf panel
    dconf_process = subprocess.Popen(['dconf', 'dump', '/org/mate/panel/'], stdout=PIPE)
    dump = dconf_process.communicate()[0].decode("UTF-8")
    with open(os.path.join(tempfile.gettempdir(),filename + '.panel'), 'w') as f:
        f.writelines(dump)

def get_non_panel_settings():
    layout = []

    layout.extend(get_maximus_undecorate())
    layout.extend(get_window_control_layout())

    return layout

def get_maximus_undecorate():
    VALID = {'mate-maximus-undecorate': 'undecorate'}

    schemas = {'mate-maximus-undecorate': 'org.mate.maximus'}

    paths = {'mate-maximus-undecorate': '/org/mate/maximus/'}

    layout = []
    layout.append('[Customsetting maximusdecoration]\n')
    layout.extend(collect_simple_settings(VALID, schemas, paths, False))

    # We needed a way to determine if the user chose a different
    # maximus undecorated setting as opposed to the setting not
    # being present (old version of mate-tweak or just not in
    # dconf)
    if any('mate-maximus-undecorate' in entry for entry in layout):
        layout.append('mate-maximus-recorded=True\n')
    else:
        layout.append('mate-maximus-recorded=False\n')

    layout.append('\n')
    return layout

def get_window_control_layout():
    VALID = {'mate-general': 'button-layout',
             'mate-interface': 'gtk-decoration-layout',
             'gnome-wm-preferences': 'button-layout'}

    schemas = {'mate-general': 'org.mate.Marco.general',
               'mate-interface': 'org.mate.interface',
               'gnome-wm-preferences': 'org.gnome.desktop.wm.preferences'}

    paths = {'mate-general': '/org/mate/Macro/general/',
             'mate-interface': '/org/mate/interface/',
             'gnome-wm-preferences': '/org/gnome/desktop/wm/preferences/'}

    layout = []
    layout.append('[Customsetting windowcontrollayout]\n')
    layout.extend(collect_simple_settings(VALID, schemas, paths, True))
    
    return layout

def collect_simple_settings(valid_keys, schemas, paths, append_final_newline):
    layout = []
    for setting in schemas.keys():
        settings = Gio.Settings.new(schemas[setting])

        for key in settings.keys():
            if key == valid_keys[setting]:
                val = settings[key]
                layout.append(f"{setting}={val}\n")

    if append_final_newline:
        layout.append('\n')
    return layout


def backup_dock(filename):
    with open(os.path.join(tempfile.gettempdir(), filename + '.dock'), 'w') as f:
        f.writelines('plank')

if __name__ == '__main__':
    if len(sys.argv) == 3:
        action = sys.argv[1]
        filename = sys.argv[2]
        if action == 'autostop':
            autostop(filename)
        elif action == 'backup':
            backup_layout(filename)
        elif action == 'dock':
            backup_dock(filename)
        elif action == 'delete':
            delete_layout(filename + '.dock')
            delete_layout(filename + '.layout')
            delete_layout(filename + '.panel')
        elif action == 'install':
            install_layout(filename + '.dock')
            install_layout(filename + '.layout')
            install_layout(filename + '.panel')
    else:
        print("ERROR! No action supplied.")
        sys.exit(1)
