/**
 * Copyright (C) 2004-2011 Jive Software. All rights reserved.
 * This plugin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.jivesoftware.sparkimpl.plugin.idle;

import org.jivesoftware.Spark;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.StanzaBuilder;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.plugin.Plugin;
import org.jivesoftware.spark.util.StringUtils;
import org.jivesoftware.spark.util.log.Log;
//import org.jivesoftware.sparkimpl.plugin.phone.PhonePlugin;
import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;
import org.jivesoftware.sparkimpl.settings.local.SettingsManager;

import java.util.Timer;
import java.util.TimerTask;

/**
 * Sets idle or online status based on activity
 */
public class UserIdlePlugin extends TimerTask implements Plugin {
	private final int CHECKTIME = 2;
	private boolean hasChanged = false;
	private static final LocalPreferences pref = SettingsManager.getLocalPreferences();
	private static Presence latestPresence;
	private static String statustext;
	private static boolean isLocked;
    private IdleTimeDetector idleTimeDetector;

    @Override
	public boolean canShutDown() {
		return false;
	}

	@Override
	public void initialize() {
		Timer timer = new Timer();
		// Since 10 minutes after boot start checking every 2 minutes
		timer.schedule(this, (60 * 1000 * 10), (60 * 1000 * CHECKTIME));
        idleTimeDetector = new IdleTimeDetectorFactory().newIdleTimeDetector();

		if (Spark.isWindows()) {
            LockListener lockListener = new LockListener();
            lockListener.intWinLockListener();
		}
	}

	@Override
	public void shutdown() {
	}

	@Override
	public void uninstall() {
	}

	private void setIdle() {
		latestPresence = SparkManager.getWorkspace().getStatusBar().getPresence();
		if (!latestPresence.isAway()) {
			statustext = pref.getIdleMessage();
		} else {
			statustext = latestPresence.getStatus();
		}
		if (latestPresence.isAway()) {
			Log.debug("UserIdlePlugin: Presence is already set to away");
		} else {
            Presence statusPresence = StanzaBuilder.buildPresence()
                .ofType(Presence.Type.available)
                .setStatus(StringUtils.modifyWildcards(statustext))
                .setPriority(0)
                .setMode(Presence.Mode.away)
                .build();
			SparkManager.getSessionManager().changePresence(statusPresence);
			Log.debug("UserIdlePlugin: Setting idle presence");
		}
	}

	private void setOnline() {
		/* TODO commented out when PhonePlugin was not ported to Maven.
		if (PhonePlugin.onPhonePresence != null) {
			SparkManager.getSessionManager().changePresence(PhonePlugin.onPhonePresence);
			Log.debug("UserIdlePlugin: Returning from idle/lock - On the Phone");

		} else if ((latestPresence.getStatus().contains("On the phone")) && (PhonePlugin.offPhonePresence != null)
				&& ((PhonePlugin.offPhonePresence.getMode().equals(Presence.Mode.dnd))
				|| (PhonePlugin.offPhonePresence.getMode().equals(Presence.Mode.xa)))) {
			SparkManager.getSessionManager().changePresence(PhonePlugin.offPhonePresence);
			Log.debug("UserIdlePlugin: Matched DND/XA - Setting presence from PhonePlugin");

		} else if (((latestPresence.getStatus().contains("On the phone")) && (PhonePlugin.offPhonePresence != null)
				&& (PhonePlugin.offPhonePresence.getStatus().contentEquals(statustext)))) {
            Presence presence = StanzaBuilder.buildPresence()
                .ofType(Presence.Type.available)
                .setStatus(PhonePlugin.offPhonePresence.getStatus())
                .setPriority(1)
                .setMode(Presence.Mode.available)
                .build();
			SparkManager.getSessionManager().changePresence(presence);
			Log.debug("UserIdlePlugin: Setting presence from PhonePlugin ....");

		} else if ((latestPresence.getStatus().contains("On the phone")) && (PhonePlugin.offPhonePresence != null)) {
			SparkManager.getSessionManager().changePresence(PhonePlugin.offPhonePresence);
			Log.debug("UserIdlePlugin: Setting presence from PhonePlugin");

		} else {
		*/
			SparkManager.getSessionManager().changePresence(latestPresence);
			Log.debug("UserIdlePlugin: Setting presence using latestPresence");
		/*}*/
	}

    @Override
    public void run() {
        if (idleTimeDetector == null) {
            return;
        }
        if (!SparkManager.getConnection().isConnected()) return;
        if (!pref.isIdleOn()) {
            return;
        }

        if (isLocked) {
            if (!hasChanged) {
                setIdle();
                hasChanged = true;
            }
        } else {
            // Set idle/online status based on duration
            long idleDuration = idleTimeDetector.getIdleTimeMillis() / 1000;
            if (!hasChanged && idleDuration > pref.getIdleTime() * 60L) {
                setIdle();
                hasChanged = true;
            } else if (hasChanged && idleDuration < 10) {
                setOnline();
                hasChanged = false;
            }
        }
    }


	public static class LockListener {

		public void intWinLockListener() {
			new Thread(() -> new WinLockListener() {
                @Override
                protected void onMachineLocked(int sessionId) {
                    isLocked = true;
                }

                @Override
                protected void onMachineUnlocked(int sessionId) {
                    isLocked = false;
                }
            }).start();
		}

	}
}

