/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @authors tag. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed 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.aesh.readline;

import org.aesh.readline.completion.Completion;
import org.aesh.readline.terminal.Key;
import org.aesh.readline.tty.terminal.TestConnection;
import org.aesh.terminal.utils.Config;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * @author <a href=mailto:[email protected]">StÃ¥le W. Pedersen</a>
 */
public class CompletionReadlineTest {

    @Test
    public void testCompletion() {
        List<Completion> completions = new ArrayList<>();
        completions.add(co -> {
            if(co.getBuffer().equals("foo"))
                co.addCompletionCandidate("foobar");
        });

        completions.add(co -> {
            if(co.getBuffer().equals("bar")) {
                co.addCompletionCandidate("barfoo");
                co.doAppendSeparator(false);
            }
        });

        completions.add( co -> {
            if(co.getBuffer().equals("le")) {
                co.addCompletionCandidate("less");
                co.setSeparator(':');
            }
        });

        TestConnection term = new TestConnection(completions);

        term.read("foo".getBytes());
        term.read(Key.CTRL_I);
        term.read(Config.getLineSeparator());
        term.assertLine("foobar ");

        term.readline(completions);
        term.read("bar".getBytes());
        term.read(Key.CTRL_I);
        term.read(Config.getLineSeparator());
        term.assertLine("barfoo");

        term.readline(completions);
        term.read("le".getBytes());
        term.read(Key.CTRL_I);
        term.read(Config.getLineSeparator());
        term.assertLine("less:");
    }

    @Test
    public void testMultipleCompletionsSorted() {
        List<Completion> completions = new ArrayList<>();
        completions.add(co -> {
            if(co.getBuffer().trim().equals("")) {
                co.addCompletionCandidate("foo");
                co.addCompletionCandidate("arg");
                co.addCompletionCandidate("Arg");
                co.addCompletionCandidate("boo");
            }
        });

        TestConnection term = new TestConnection(completions);
        term.read(Key.CTRL_I);
        term.assertOutputBuffer(": "+Config.getLineSeparator()+"arg  Arg  boo  foo  "+Config.getLineSeparator()+":");
     }

    @Test
    public void testCompletionEmptyLine() {
        List<Completion> completions = new ArrayList<>();
        completions.add(co -> {
            if(co.getBuffer().trim().equals("")) {
                co.addCompletionCandidate("bar");
                co.addCompletionCandidate("foo");
            }
        });

        TestConnection term = new TestConnection(completions);

        term.read("  ".getBytes());
        term.read(Key.LEFT_2);
        term.read(Key.LEFT_2);
        term.read(Key.CTRL_I);
        term.assertOutputBuffer(":   "+Config.getLineSeparator()+"bar  foo  "+Config.getLineSeparator()+":");
        term.clearOutputBuffer();
        term.read("a");
        term.read(Config.getLineSeparator());
        term.assertLine("a  ");
    }

    @Test
    public void testCompletionMidLine() {
        List<Completion> completions = new ArrayList<>();
        completions.add(co -> {
            if(co.getBuffer().startsWith("1 ")) {
                co.addCompletionCandidate("1 foo");
            }
        });

        TestConnection term = new TestConnection(completions);

        term.read("1 bah".getBytes());
        term.read(Key.LEFT_2);
        term.read(Key.LEFT_2);
        term.read(Key.LEFT_2);
        term.read(Key.CTRL_I);
        term.assertBuffer("1 foo bah");
        term.clearOutputBuffer();
        term.read("A");
        term.read(Config.getLineSeparator());
        term.assertLine("1 foo Abah");
    }


    @Test
    public void testCompletionsMidLine() {
        List<Completion> completions = new ArrayList<>();
        completions.add(co -> {
            if(co.getBuffer().startsWith("1 ")) {
                co.addCompletionCandidate("bar");
                co.addCompletionCandidate("foo");
            }
        });

        TestConnection term = new TestConnection(completions);

        term.read("1 bah".getBytes());
        term.read(Key.LEFT_2);
        term.read(Key.LEFT_2);
        term.read(Key.LEFT_2);
        term.read(Key.CTRL_I);
        term.assertOutputBuffer(": 1 bah"+Config.getLineSeparator()+"bar  foo  "+Config.getLineSeparator()+": 1 bah");
        term.clearOutputBuffer();
        term.read("A");
        term.read(Config.getLineSeparator());
        term.assertLine("1 Abah");
    }

    @Test
    public void testBIIIGCompletion() {

        String completionWord = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy/";
        List<Completion> completions = new ArrayList<>();
        completions.add(co -> {
            if(co.getBuffer().trim().endsWith("1")) {
                co.addCompletionCandidate(completionWord);
                co.doAppendSeparator(false);
                co.setIgnoreOffset(true);
            }
            else {
                co.addCompletionCandidate(completionWord);
                co.setIgnoreOffset(true);
                co.doAppendSeparator(true);
            }
        });

        TestConnection term = new TestConnection(completions);

        term.read("1 ".getBytes());
        term.read(Key.CTRL_I);
        term.assertOutputBuffer(": 1 "+completionWord);
        term.read("/".getBytes());
        term.read(Key.CTRL_I);
        term.assertOutputBuffer(": 1 "+completionWord+"/"+completionWord);
        term.clearOutputBuffer();
        term.read(Config.getLineSeparator());
    }

}