/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.sling.fsprovider.internal;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.vault.util.PlatformNameFormat;
import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
import org.apache.sling.fsprovider.internal.mapper.ContentFile;
import org.apache.sling.fsprovider.internal.parser.ContentElement;
import org.apache.sling.fsprovider.internal.parser.ContentFileCache;
import org.apache.sling.spi.resource.provider.ObservationReporter;
import org.apache.sling.spi.resource.provider.ObserverConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class is a monitor for the file system
 * that periodically checks for changes.
 */
public final class FileMonitor extends TimerTask {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private final Timer timer = new Timer();
    private boolean stop = false;
    private boolean stopped = true;

    private final Monitorable root;

    private final FsResourceProvider provider;
    private final FsMode fsMode;
    private final ContentFileExtensions contentFileExtensions;
    private final ContentFileCache contentFileCache;

    /**
     * Creates a new instance of this class.
     * @param provider The resource provider.
     * @param interval The interval between executions of the task, in milliseconds.
     * @param fsMode FS mode
     * @param contentFileExtensions Content file extensions
     * @param contentFileCache Content file cache
     */
    public FileMonitor(final FsResourceProvider provider, final long interval, FsMode fsMode,
            final ContentFileExtensions contentFileExtensions, final ContentFileCache contentFileCache) {
        this.provider = provider;
        this.fsMode = fsMode;
        this.contentFileExtensions = contentFileExtensions;
        this.contentFileCache = contentFileCache;
        
        File rootFile = this.provider.getRootFile();
        if (fsMode == FsMode.FILEVAULT_XML) {
            rootFile = new File(this.provider.getRootFile(), "." + PlatformNameFormat.getPlatformPath(this.provider.getProviderRoot()));
        }
        this.root = new Monitorable(this.provider.getProviderRoot(), rootFile, null);
        
        createStatus(this.root, contentFileExtensions, contentFileCache);
        log.debug("Starting file monitor for {} with an interval of {}ms", this.root.file, interval);
        timer.schedule(this, 0, interval);
    }

    /**
     * Stop periodically executing this task. If the task is currently executing it
     * will never be run again after the current execution, otherwise it will simply
     * never run (again).
     */
    void stop() {
        synchronized (timer) {
            if (!stop) {
                stop = true;
                cancel();
                timer.cancel();
            }

            boolean interrupted = false;
            while (!stopped) {
                try {
                    timer.wait();
                }
                catch (InterruptedException e) {
                    interrupted = true;
                }
            }
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
        log.debug("Stopped file monitor for {}", this.root.file);
    }

    /**
     * @see java.util.TimerTask#run()
     */
    @Override
    public void run() {
        synchronized (timer) {
            stopped = false;
            if (stop) {
                stopped = true;
                timer.notifyAll();
                return;
            }
        }
        synchronized ( this ) {
            try {
                // if we don't have an observation reporter, we just skip the check
                final ObservationReporter reporter = this.provider.getObservationReporter();
                if ( reporter != null ) {
                    this.check(this.root, reporter);
                }
            } catch (Exception e) {
                // ignore this
            }
        }
        synchronized (timer) {
            stopped = true;
            timer.notifyAll();
        }
    }

    /**
     * Check the monitorable
     * @param monitorable The monitorable to check
     * @param reporter The ObservationReporter
     */
    private void check(final Monitorable monitorable, final ObservationReporter reporter) {
        log.trace("Checking {}", monitorable.file);
        // if the file is non existing, check if it has been readded
        if ( monitorable.status instanceof NonExistingStatus ) {
            if ( monitorable.file.exists() ) {
                // new file and reset status
                createStatus(monitorable, contentFileExtensions, contentFileCache);
                sendEvents(monitorable, ChangeType.ADDED, reporter);
                final FileStatus fs = (FileStatus)monitorable.status;
                if ( fs instanceof DirStatus ) {
                    final DirStatus ds = (DirStatus)fs;
                    // remove monitorables for new folder and update folder children to send events for directory contents
                    ds.children = new Monitorable[0];
                    checkDirStatusChildren(monitorable, reporter);
                }
            }
        } else {
            // check if the file has been removed
            if ( !monitorable.file.exists() ) {
                // removed file and update status
                sendEvents(monitorable, ChangeType.REMOVED, reporter);
                monitorable.status = NonExistingStatus.SINGLETON;
                contentFileCache.remove(transformPath(monitorable.path));
            } else {
                // check for changes
                final FileStatus fs = (FileStatus)monitorable.status;
                boolean changed = false;
                if ( fs.lastModified < monitorable.file.lastModified() ) {
                    fs.lastModified = monitorable.file.lastModified();
                    // changed
                    sendEvents(monitorable, ChangeType.CHANGED, reporter);
                    changed = true;
                    contentFileCache.remove(transformPath(monitorable.path));
                }
                if ( fs instanceof DirStatus ) {
                    // directory
                    final DirStatus ds = (DirStatus)fs;
                    for(int i=0; i<ds.children.length; i++) {
                        check(ds.children[i], reporter);
                    }
                    // if the dir changed we have to update
                    if ( changed ) {
                        // and now update
                        checkDirStatusChildren(monitorable, reporter);
                    }
                }
            }
        }
    }
    
    private void checkDirStatusChildren(final Monitorable dirMonitorable, final ObservationReporter reporter) {
        final DirStatus ds = (DirStatus)dirMonitorable.status;
        final File[] files = dirMonitorable.file.listFiles();
        if (files != null) {
            final Monitorable[] children = new Monitorable[files.length];
            for (int i = 0; i < files.length; i++) {
                // search in old list
                for (int m = 0; m < ds.children.length; m++) {
                    if (ds.children[m].file.equals(files[i])) {
                        children[i] = ds.children[m];
                        break;
                    }
                }
                if (children[i] == null) {
                    children[i] = new Monitorable(dirMonitorable.path + '/' + files[i].getName(), files[i],
                            contentFileExtensions.getSuffix(files[i]));
                    children[i].status = NonExistingStatus.SINGLETON;
                    check(children[i], reporter);
                }
            }
            ds.children = children;
        } else {
            ds.children = new Monitorable[0];
        }
    }

    /**
     * Send the event async via the event admin.
     */
    private void sendEvents(final Monitorable monitorable, final ChangeType changeType, final ObservationReporter reporter) {
        if (log.isDebugEnabled()) {
            log.debug("Detected change for resource {} : {}", transformPath(monitorable.path), changeType);
        }

        List<ResourceChange> changes = null;
        for (final ObserverConfiguration config : reporter.getObserverConfigurations()) {
            if (config.matches(transformPath(monitorable.path))) {
                if (changes == null) {
                    changes = collectResourceChanges(monitorable, changeType);
                }
                if (log.isTraceEnabled()) {
                    for (ResourceChange change : changes) {
                        log.debug("Send change for resource {}: {} to {}", change.getPath(), change.getType(), config);
                    }
                }
            }
        }
        if (changes != null) {
            reporter.reportChanges(changes, false);
        }
    }
    
    /**
     * Transform path for resource event.
     * @param path Path
     * @return Transformed path
     */
    private String transformPath(String path) {
        if (fsMode == FsMode.FILEVAULT_XML) {
            return PlatformNameFormat.getRepositoryPath(path);
        }
        else {
            return path;
        }
    }
    
    private List<ResourceChange> collectResourceChanges(final Monitorable monitorable, final ChangeType changeType) {
        List<ResourceChange> changes = new ArrayList<>();
        if (monitorable.status instanceof ContentFileStatus) {
            ContentFile contentFile = ((ContentFileStatus)monitorable.status).contentFile;
            if (changeType == ChangeType.CHANGED) {
                ContentElement content = contentFile.getContent();
                // we cannot easily report the diff of resource changes between two content files
                // so we simulate a removal of the toplevel node and then add all nodes contained in the current content file again.
                changes.add(buildContentResourceChange(ChangeType.REMOVED,  transformPath(monitorable.path)));
                addContentResourceChanges(changes, ChangeType.ADDED, content, transformPath(monitorable.path));
            }
            else {
                addContentResourceChanges(changes, changeType, contentFile.getContent(), transformPath(monitorable.path));
            }
        }
        else {
            changes.add(buildContentResourceChange(changeType, transformPath(monitorable.path)));
        }
        return changes;
    }
    private void addContentResourceChanges(final List<ResourceChange> changes, final ChangeType changeType,
            final ContentElement content, final String path) {
        changes.add(buildContentResourceChange(changeType,  path));
        if (content != null) {
            for (Map.Entry<String,ContentElement> entry : content.getChildren().entrySet()) {
                String childPath = path + "/" + entry.getKey();
                addContentResourceChanges(changes, changeType, entry.getValue(), childPath);
            }
        }
    }
    private ResourceChange buildContentResourceChange(final ChangeType changeType, final String path) {
        return new ResourceChange(changeType, path, false, null, null, null);
    }

    /**
     * Create a status object for the monitorable
     */
    private static void createStatus(final Monitorable monitorable, ContentFileExtensions contentFileExtensions, ContentFileCache contentFileCache) {
        if ( !monitorable.file.exists() ) {
            monitorable.status = NonExistingStatus.SINGLETON;
        } else if ( monitorable.file.isFile() ) {
            if (contentFileExtensions.matchesSuffix(monitorable.file)) {
                monitorable.status = new ContentFileStatus(monitorable.file,
                        new ContentFile(monitorable.file, monitorable.path, null, contentFileCache));
            }
            else {
                monitorable.status = new FileStatus(monitorable.file);
            }
        } else {
            monitorable.status = new DirStatus(monitorable.file, monitorable.path, contentFileExtensions, contentFileCache);
        }
    }

    /** The monitorable to hold the resource path, the file and the status. */
    private static final class Monitorable {
        public final String path;
        public final File file;
        public Object status;
        public Monitorable(final String path, final File file, String contentFileSuffix) {
            this.file = file;
            if (contentFileSuffix != null) {
                this.path = StringUtils.substringBeforeLast(path, contentFileSuffix);
            }
            else {
                this.path = path;
            }
        }
    }

    /** Status for files. */
    private static class FileStatus {
        public long lastModified;
        public FileStatus(final File file) {
            this.lastModified = file.lastModified();
        }
    }
    
    /** Status for content files */
    private static class ContentFileStatus extends FileStatus {
        public final ContentFile contentFile;
        public ContentFileStatus(final File file, final ContentFile contentFile) {
            super(file);
            this.contentFile = contentFile;
        }
    }
    
    /** Status for directories. */
    private static final class DirStatus extends FileStatus {
        public Monitorable[] children;

        public DirStatus(final File dir, final String path,
                final ContentFileExtensions contentFileExtensions, final ContentFileCache contentFileCache) {
            super(dir);
            final File[] files = dir.listFiles();
            if (files != null) {
                this.children = new Monitorable[files.length];
                for (int i = 0; i < files.length; i++) {
                    this.children[i] = new Monitorable(path + '/' + files[i].getName(), files[i],
                            contentFileExtensions.getSuffix(files[i]));
                    FileMonitor.createStatus(this.children[i], contentFileExtensions, contentFileCache);
                }
            } else {
                this.children = new Monitorable[0];
            }
        }
    }

    /** Status for non existing files. */
    private static final class NonExistingStatus {
        public static NonExistingStatus SINGLETON = new NonExistingStatus();
    }
}