package istlab.KisoJikken;

import java.io.IOException;

import com.googlecode.lanterna.SGR;
import com.googlecode.lanterna.TerminalPosition;
import com.googlecode.lanterna.TextColor;
import com.googlecode.lanterna.terminal.DefaultTerminalFactory;
import com.googlecode.lanterna.terminal.Terminal;

public class Tutorial01 {
    public static void main(String[] args) throws InterruptedException {
        /*
        This is the first tutorial and entrypoint for learning more about how to use lanterna. We will use the lower
        layer in this tutorial to demonstrate how to move around the cursor and how to output text in different
        styles and color.
        */

        /*
        First of all, we need to get hold of a Terminal object. This will be our main way of interacting with the
        terminal itself. There are a couple of implementation available and it's important you pick the correct one:
         * UnixTerminal - Uses ANSI escape codes through standard input/output to carry out the operations
         * SwingTerminal - Creates a Swing JComponent extending surface that is implementing a terminal emulator
         * SwingTerminalFrame - Creates a Swing JFrame containing a surface that is implementing a terminal emulator
         * AWTTerminal - Creates an AWT Component extending surface that is implementing a terminal emulator
         * AWTTerminalFrame - Creates an AWT Frame containing a surface that is implementing a terminal emulator
         * TelnetTerminal - Through TelnetTerminalServer, this allows you control the output to the client through the Terminal interface
         * VirtualTerminal - Complete in-memory implementation
        If you intend to write a program that runs in a standard console, like for example on a remote server you're
        connecting to through some terminal emulator and ssh, what you want is UnixTerminal. However, when developing
        the program in your IDE, you might have issues as the IDE's console probably doesn't implement the ANSI escape
        codes correctly and the output is complete garbage. Because of this, you might want to use one of the graphical
        terminal emulators (Swing or AWT), which will open a new window when you run the program instead of writing to
        standard output, and then switch to UnixTerminal when the application is ready. In order to simplify this,
        lanterna provides a TerminalFactory with a DefaultTerminalFactory implementation that tries to figure out which
        implementation to use. It's mainly checking for if the runtime system has a graphical frontend or not (i.e. if
        Java considers the system headless) and if Java is detecting a semi-standard terminal or not (checking if
        System.console() returns something), giving you either a terminal emulator or a UnixTerminal.
        */

        DefaultTerminalFactory defaultTerminalFactory = new DefaultTerminalFactory();
        /*
        The DefaultTerminalFactory can be further tweaked, but we'll leave it with default settings in this tutorial.
         */

        Terminal terminal = null;
        try {
            /*
            Let the factory do its magic and figure out which implementation to use by calling createTerminal()
             */
            terminal = defaultTerminalFactory.createTerminal();

            /*
            If we got a terminal emulator (probably Swing) then we are currently looking at an empty terminal emulator
            window at this point. If the code ran in another terminal emulator (putty, gnome-terminal, konsole, etc) by
            invoking java manually, there is yet no changes to the content.
             */

            /*
            Let's print some text, this has the same as calling System.out.println("Hello");
             */
            terminal.putCharacter('H');
            terminal.putCharacter('e');
            terminal.putCharacter('l');
            terminal.putCharacter('l');
            terminal.putCharacter('o');
            terminal.putCharacter('\n');
            terminal.flush();
            /*
            Notice the flush() call above; it is necessary to finish off terminal output operations with a call to
            flush() both in the case of native terminal and the bundled terminal emulators. Lanterna's Unix terminal
            doesn't buffer the output by itself but one can assume the underlying I/O layer does. In the case of the
            terminal emulators bundled in lanterna, the flush call will signal a repaint to the underlying UI component.
             */
            Thread.sleep(2000);

            /*
            At this point the cursor should be on start of the next line, immediately after the Hello that was just
            printed. Let's move the cursor to a new position, relative to the current position. Notice we still need to
            call flush() to ensure the change is immediately visible (i.e. the user can see the text cursor moved to the
            new position).
            One thing to notice here is that if you are running this in a 'proper' terminal and the cursor position is
            at the bottom line, it won't actually move the text up. Attempts at setting the cursor position outside the
            terminal bounds are usually rounded to the first/last column/row. If you run into this, please clear the
            terminal content so the cursor is at the top again before running this code.
             */
            TerminalPosition startPosition = terminal.getCursorPosition();
            terminal.setCursorPosition(startPosition.withRelativeColumn(3).withRelativeRow(2));
            terminal.flush();
            Thread.sleep(2000);

            /*
            Let's continue by changing the color of the text printed. This doesn't change any currently existing text,
            it will only take effect on whatever we print after this.
             */
            terminal.setBackgroundColor(TextColor.ANSI.BLUE);
            terminal.setForegroundColor(TextColor.ANSI.YELLOW);

            /*
            Now print text with these new colors
             */
            terminal.putCharacter('Y');
            terminal.putCharacter('e');
            terminal.putCharacter('l');
            terminal.putCharacter('l');
            terminal.putCharacter('o');
            terminal.putCharacter('w');
            terminal.putCharacter(' ');
            terminal.putCharacter('o');
            terminal.putCharacter('n');
            terminal.putCharacter(' ');
            terminal.putCharacter('b');
            terminal.putCharacter('l');
            terminal.putCharacter('u');
            terminal.putCharacter('e');
            terminal.flush();
            Thread.sleep(2000);

            /*
            In addition to colors, most terminals supports some sort of style that can be selectively enabled. The most
            common one is bold mode, which on many terminal implementations (emulators and otherwise) is not actually
            using bold text at all but rather shifts the tint of the foreground color so it stands out a bit. Let's
            print the same text as above in bold mode to compare.
            Notice that startPosition has the same value as when we retrieved it with getTerminalSize(), the
            TerminalPosition class is immutable and calling the with* methods will return a copy. So the following
            setCursorPosition(..) call will put us exactly one row below the previous row.
             */
            terminal.setCursorPosition(startPosition.withRelativeColumn(3).withRelativeRow(3));
            terminal.flush();
            Thread.sleep(2000);
            terminal.enableSGR(SGR.BOLD);
            terminal.putCharacter('Y');
            terminal.putCharacter('e');
            terminal.putCharacter('l');
            terminal.putCharacter('l');
            terminal.putCharacter('o');
            terminal.putCharacter('w');
            terminal.putCharacter(' ');
            terminal.putCharacter('o');
            terminal.putCharacter('n');
            terminal.putCharacter(' ');
            terminal.putCharacter('b');
            terminal.putCharacter('l');
            terminal.putCharacter('u');
            terminal.putCharacter('e');
            terminal.flush();
            Thread.sleep(2000);

            /*
            Ok, that's enough for now. Let's reset colors and SGR modifiers and move down one more line
             */
            terminal.resetColorAndSGR();
            terminal.setCursorPosition(terminal.getCursorPosition().withColumn(0).withRelativeRow(1));
            terminal.putCharacter('D');
            terminal.putCharacter('o');
            terminal.putCharacter('n');
            terminal.putCharacter('e');
            terminal.putCharacter('\n');
            terminal.flush();

            Thread.sleep(2000);

            /*
            Beep and exit
             */
            terminal.bell();
            terminal.flush();
            Thread.sleep(200);
        }
        catch(IOException e) {
            e.printStackTrace();
        }
        finally {
            if(terminal != null) {
                try {
                    /*
                    Closing the terminal doesn't always do something, but if you run the Swing or AWT bundled terminal
                    emulators for example, it will close the window and allow this application to terminate. Calling it
                    on a UnixTerminal will not have any affect.
                     */
                    terminal.close();
                }
                catch(IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
