package io.github.minecraftgui.models.components;
import io.github.minecraftgui.controllers.Render;
import io.github.minecraftgui.models.Updatable;
import io.github.minecraftgui.models.fonts.Font;
import java.util.ArrayList;
/**
* Created by Samuel on 2015-11-15.
*/
public class Line implements Updatable, Drawable {
private final ComponentText componentText;
private ArrayList<Char> lineChar;
private Char cursorLocation = null;
private boolean updateText = false;
private Font fontLastUpdate = null;
private double widthLastUpdate = 0;
private double xRelative = 0;
private String text = "";
private String lastTextVersion = "";
private String visibleText = "";
private Char firstCharVisible = null;
private Char lastCharVisible = null;
private boolean isTextUpdated = false;
public Line(ComponentText componentText) {
this.componentText = componentText;
lineChar = new ArrayList<>();
}
public boolean isTextUpdated() {
return isTextUpdated;
}
public String getVisibleText(){
return visibleText;
}
@Override
public String toString() {
return text;
}
public double getCursorX(){
if(cursorLocation != null)
return cursorLocation.cursorX - xRelative;
else
return 0;
}
public double getCursorY(){
return 0;
}
public void setCursorLocation(double x, double y){
double lineHeight = componentText.getStringHeight();
int lineIndex = (int) (y/lineHeight);
if(lineIndex == 0) {
String currentLine = "";
for (Char c : lineChar) {
currentLine = currentLine+c.getValue();
if (componentText.getStringWidth(currentLine) >= x+xRelative) {
cursorLocation = c;
return;
}
}
cursorLocation = null;
}
}
public void moveCursorLeft(){
if(cursorLocation != null) {
cursorLocation = cursorLocation.before;
updateVisibleText();
}
}
public void moveCursorRight(){
if(cursorLocation != null && cursorLocation.after != null) {
cursorLocation = cursorLocation.after;
updateVisibleText();
}
else if(cursorLocation == null) {
if (lineChar.size() != 0 && lineChar.get(0) != null) {
cursorLocation = lineChar.get(0);
updateVisibleText();
}
}
}
public void setText(String text){
ArrayList<String> words = split(text);
lineChar.clear();
for(String word : words) {
for (char c : word.toCharArray()) {
Char ch = new Char(c);
lineChar.add(ch);
}
}
if(lineChar.size() == 1)
cursorLocation = lineChar.get(0);
else
cursorLocation = null;
updateText = true;
}
public void deleteNextChar(){
if(cursorLocation != null) {
if (cursorLocation.after != null) {
Char c = cursorLocation.after;
lineChar.remove(c);
updateText = true;
}
}
else if (lineChar.size() != 0 && lineChar.get(0) != null) {
Char c = lineChar.get(0);
lineChar.remove(c);
updateText = true;
}
}
public void deleteChar(){
if(cursorLocation != null){
Char c = cursorLocation;
lineChar.remove(c);
cursorLocation = c.before;
updateText = true;
}
}
public void addInput(char input){
if(input != 10 && input != 13) {
if (text.length() == 0)
setText(String.valueOf(input));
else if (cursorLocation != null) {
Char c = new Char(input);
lineChar.add(lineChar.indexOf(cursorLocation)+1, c);
cursorLocation = c;
updateText = true;
} else {
Char c = new Char(input);
lineChar.add(0, c);
cursorLocation = c;
updateText = true;
}
}
}
@Override
public void update(long updateId) {
isTextUpdated = false;
if(widthLastUpdate != componentText.getWidth() || updateText){
widthLastUpdate = componentText.getWidth();
updateText = true;
}
if(fontLastUpdate != componentText.getFont() || updateText){
fontLastUpdate = componentText.getFont();
updateText = true;
}
if(updateText){
lastTextVersion = text;
text = "";
updateLine();
for(int i = 0; i < lineChar.size(); i++){
Char c = lineChar.get(i);
if(i == 0)
c.before = null;
else
c.before = lineChar.get(i-1);
if(i+1 == lineChar.size())
c.after = null;
else
c.after = lineChar.get(i+1);
}
updateVisibleText();
updateText = false;
isTextUpdated = true;
}
}
private void updateVisibleText(){
if(text.length() != 0) {
if (componentText.getStringWidth(text) <= componentText.getWidth()) {
visibleText = text;
firstCharVisible = null;
lastCharVisible = lineChar.get(lineChar.size()-1);
xRelative = 0;
}
else if (cursorLocation == null) {
firstCharVisible = null;
for (int i = 0; i < lineChar.size(); i++){
if (componentText.getStringWidth(text.substring(0, i)) > componentText.getWidth()) {
visibleText = text.substring(0, i - 1);
firstCharVisible = null;
lastCharVisible = lineChar.get(i-2);
xRelative = 0;
return;
}
}
} else if(firstCharVisible == cursorLocation){
int firstIndex = lineChar.indexOf(firstCharVisible);
if(firstIndex != 0){
for (int i = --firstIndex; i <= lineChar.size(); i++){
if (componentText.getStringWidth(text.substring(firstIndex, i)) > componentText.getWidth()) {
visibleText = text.substring(firstIndex, i - 1);
firstCharVisible = lineChar.get(firstIndex);
lastCharVisible = lineChar.get(i-2);
xRelative = componentText.getStringWidth(text.substring(0, firstIndex));
return;
}
}
visibleText = text.substring(firstIndex, text.length());
firstCharVisible = lineChar.get(firstIndex);
lastCharVisible = lineChar.get(lineChar.size()-1);
xRelative = componentText.getStringWidth(text.substring(0, firstIndex));
}
else{
firstCharVisible = null;
for (int i = 0; i < lineChar.size(); i++){
if (componentText.getStringWidth(text.substring(0, i)) > componentText.getWidth()) {
visibleText = text.substring(0, i - 1);
firstCharVisible = null;
lastCharVisible = lineChar.get(i-2);
xRelative = 0;
return;
}
}
}
}
else if(lastCharVisible == cursorLocation){
int lastIndex = lineChar.indexOf(lastCharVisible);
if(lastIndex+1 != lineChar.size()) {
++lastIndex;
for (int i = lastIndex; i >= 0; i--) {
if (componentText.getStringWidth(text.substring(i, lastIndex + 1)) > componentText.getWidth()) {
visibleText = text.substring(i+1, lastIndex + 1);
firstCharVisible = lineChar.get(i + 1);
lastCharVisible = lineChar.get(lastIndex);
xRelative = componentText.getStringWidth(text.substring(0, i + 1));
return;
}
visibleText = text.substring(0, lastIndex + 1);
firstCharVisible = lineChar.get(0);
lastCharVisible = lineChar.get(lastIndex);
xRelative = 0;
}
}
}
else if(lastTextVersion.length() < text.length()){
int indexFirst = lineChar.indexOf(firstCharVisible);
int indexCursor = lineChar.indexOf(cursorLocation);
int distanceBetweenFirstAndCusor = indexFirst - indexCursor;
if(distanceBetweenFirstAndCusor == 1 || distanceBetweenFirstAndCusor == -1){
if(distanceBetweenFirstAndCusor > 0)
--indexFirst;
if( indexFirst == -1)
indexFirst = 0;
for (int i = indexFirst; i <= lineChar.size(); i++){
if (componentText.getStringWidth(text.substring(indexFirst, i)) > componentText.getWidth()) {
visibleText = text.substring(indexFirst, i - 1);
firstCharVisible = lineChar.get(indexFirst);
lastCharVisible = lineChar.get(i-2);
xRelative = componentText.getStringWidth(text.substring(0, indexFirst));
return;
}
}
visibleText = text.substring(indexFirst, text.length());
firstCharVisible = lineChar.get(indexFirst);
lastCharVisible = lineChar.get(lineChar.size()-1);
xRelative = componentText.getStringWidth(text.substring(0, indexFirst));
}
else {
int lastIndex = lineChar.indexOf(lastCharVisible);
if (lineChar.indexOf(cursorLocation) + 1 == lineChar.size())
lastIndex++;
for (int i = lastIndex; i >= 0; i--) {
if (componentText.getStringWidth(text.substring(i, lastIndex + 1)) > componentText.getWidth()) {
visibleText = text.substring(i + 1, lastIndex + 1);
firstCharVisible = lineChar.get(i + 1);
lastCharVisible = lineChar.get(lastIndex);
xRelative = componentText.getStringWidth(text.substring(0, i + 1));
return;
}
visibleText = text.substring(0, lastIndex + 1);
firstCharVisible = lineChar.get(0);
lastCharVisible = lineChar.get(lastIndex);
xRelative = 0;
}
}
}
else if(lastTextVersion.length() > text.length()){
int firstIndex = lineChar.indexOf(firstCharVisible);
if(firstIndex >= 1){
for (int i = firstIndex; i <= lineChar.size(); i++){
if (componentText.getStringWidth(text.substring(firstIndex, i)) > componentText.getWidth()) {
visibleText = text.substring(firstIndex, i - 1);
firstCharVisible = lineChar.get(firstIndex);
lastCharVisible = lineChar.get(i-2);
xRelative = componentText.getStringWidth(text.substring(0, firstIndex));
return;
}
}
visibleText = text.substring(firstIndex, text.length());
firstCharVisible = lineChar.get(firstIndex);
lastCharVisible = lineChar.get(lineChar.size()-1);
xRelative = componentText.getStringWidth(text.substring(0, firstIndex));
}
else{
firstCharVisible = null;
for (int i = 0; i < lineChar.size(); i++){
if (componentText.getStringWidth(text.substring(0, i)) > componentText.getWidth()) {
visibleText = text.substring(0, i - 1);
firstCharVisible = null;
lastCharVisible = lineChar.get(i-2);
xRelative = 0;
return;
}
}
}
}
}
else
visibleText = "";
}
private void updateLine(){
for(int i = 0; i < lineChar.size(); i++) {
Char c = lineChar.get(i);
this.text += c.getValue();
c.cursorX = componentText.getStringWidth(text.substring(0, i+1));
}
}
private ArrayList<String> split(String text){
ArrayList<String> words = new ArrayList<>();
String word = "";
for(int i = 0; i < text.length(); i++){
if(text.charAt(i) != 13 && text.charAt(i) != 10) {
if (text.charAt(i) == 32) {
if (!word.equals("")) {
words.add(word);
word = "";
}
words.add(" ");
} else
word += text.charAt(i);
}
if(i+1 == text.length() && text.charAt(i) != 32 && text.charAt(i) != 13 && text.charAt(i) != 10)
words.add(word);
}
return words;
}
@Override
public void draw(Render render) {
componentText.getFont().drawString(getVisibleText(), componentText.getY(), componentText.getX(), componentText.getFontSize(), componentText.getFontColor());
}
private class Char {
private double cursorX;
private Char before;
private Char after;
private final String value;
private Char(char value) {
this.value = String.valueOf(value);
}
public String getValue() {
return value;
}
}
}