/*
 * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
 * @bug 4313887
 * @summary Sanity test for Sun-specific sensitivyt level watch event modifier
 * @library ..
 * @run main/timeout=330 Basic
 */

import java.nio.file.*;
import static java.nio.file.StandardWatchEventKind.*;
import java.io.OutputStream;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import com.sun.nio.file.SensitivityWatchEventModifier;

public class SensitivityModifier {

    static final Random rand = new Random();

    static void register(Path[] dirs, WatchService watcher) throws IOException {
        SensitivityWatchEventModifier[] sensitivtives =
            SensitivityWatchEventModifier.values();
        for (int i=0; i<dirs.length; i++) {
            SensitivityWatchEventModifier sensivity =
                sensitivtives[ rand.nextInt(sensitivtives.length) ];
            Path dir = dirs[i];
            dir.register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_MODIFY }, sensivity);
        }
    }

    static void doTest(Path top) throws Exception {
        FileSystem fs = top.getFileSystem();
        WatchService watcher = fs.newWatchService();

        // create directories and files
        int nDirs = 5 + rand.nextInt(20);
        int nFiles = 50 + rand.nextInt(50);
        Path[] dirs = new Path[nDirs];
        Path[] files = new Path[nFiles];
        for (int i=0; i<nDirs; i++) {
            dirs[i] = top.resolve("dir" + i).createDirectory();
        }
        for (int i=0; i<nFiles; i++) {
            Path dir = dirs[rand.nextInt(nDirs)];
            files[i] = dir.resolve("file" + i).createFile();
        }

        // register the directories (random sensitivity)
        register(dirs, watcher);

        // sleep a bit here to ensure that modification to the first file
        // can be detected by polling implementations (ie: last modified time
        // may not change otherwise).
        try { Thread.sleep(1000); } catch (InterruptedException e) { }

        // modify files and check that events are received
        for (int i=0; i<10; i++) {
            Path file = files[rand.nextInt(nFiles)];
            System.out.println("Modify: " + file);
            OutputStream out = file.newOutputStream();
            try {
                out.write(new byte[100]);
            } finally {
                out.close();
            }
            System.out.println("Waiting for event...");
            WatchKey key = watcher.take();
            WatchEvent<?> event = key.pollEvents().iterator().next();
            if (event.kind() != ENTRY_MODIFY)
                throw new RuntimeException("Unexpected event: " + event);
            Path name = ((WatchEvent<Path>)event).context();
            if (!name.equals(file.getName()))
                throw new RuntimeException("Unexpected context: " + name);
            System.out.println("Event OK");

            // drain events (to avoid interference)
            do {
                key.reset();
                key = watcher.poll(1, TimeUnit.SECONDS);
            } while (key != null);

            // re-register the directories to force changing their sensitivity
            // level
            register(dirs, watcher);
        }

        // done
        watcher.close();
    }

    public static void main(String[] args) throws Exception {
        Path dir = TestUtil.createTemporaryDirectory();
        try {
            doTest(dir);
        } finally {
            TestUtil.removeAll(dir);
        }
    }
}
