package nz.colin.mathml.utility;

import nu.xom.*;
import nz.colin.mathml.domain.Replacement;
import nz.colin.mathml.domain.Style;
import nz.colin.mathml.domain.TextMap;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Created by colin on 28/08/16.
 */
public class CharReplacer {
    private final Replacement replacement;

    private Style style;

    public CharReplacer(Style style) {
        this.replacement = new Replacement();
        this.style = style;
    }

    public void replace(Element root){
        Nodes chars = root.query("//char");
        for(int i = 0; i < chars.size(); i++){
            String mtCode = chars.get(i).query("mt_code_value").get(0).getValue();
            TextMap map = this.replacement.testRange(mtCode);
            if(map != null){
                doReplacement(map, chars.get(i));
            }
        }
    }

    private void doReplacement(TextMap map, Node node){
        String mode = node.query("variation").get(0).getValue();
        Method[] methods = map.getClass().getMethods();
        Method methodToCall = null;
        for(int i = 0; i < methods.length; i++){
            if(methods[i].getName().toLowerCase().contains(mode)){
                methodToCall = methods[i];break;
            }
        }

        String mtCode = node.query("mt_code_value").get(0).getValue().substring(2);

        String replacedStr = null;

        try {
            replacedStr = (String) methodToCall.invoke(map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }


        if(replacedStr.contains("(Char)")){
            replacedStr = replacedStr.replace("(Char)", "" + (char) Integer.parseInt(mtCode,16));
        }else{
            replacedStr = replacedStr.replace("(CharHex)", "&#x" + mtCode + ";");
        }

        Element m = new Element(replacedStr.substring(1,3));
        if (mode.equals("textmode")) {
            m = new Element("mtext");
            Style.FontStyle fontStyle = style.getFontStyle("text");
            String styleStr = getFontStyleStr(fontStyle);
            if (styleStr != null) {
                m.addAttribute(new Attribute("mathvariant", styleStr));
            }
        } else if (mode.equals("mathmode")) {
            Style.FontStyle fontStyle = style.getFontStyle("variable");
            String styleStr = getFontStyleStr(fontStyle);
            if (styleStr != null) {
                switch (m.getLocalName()) {
                    case "mn":
                    case "mi":
                        m.addAttribute(new Attribute("mathvariant", styleStr));
                        break;
                    case "mo":
                        if (styleStr.contains("bold")) {
                            m.addAttribute(new Attribute("mathvariant", "bold"));
                        }
                        break;
                }
            }
        }
        m.appendChild(replacedStr.substring(4, replacedStr.length() - 5));

        Element parent = (Element) node.getParent();
        Elements children = parent.getChildElements();
        for(int j = 0; j < children.size(); j++){
            if(children.get(j) == node){
                parent.insertChild(m, j);
                node.detach();
                break;
            }
        }
    }

    private String getFontStyleStr(Style.FontStyle fontStyle) {
        String styleStr = null;
        if (fontStyle.isBold()) {
            if (fontStyle.isItalic()) {
                styleStr = "bold-italic";
            } else {
                styleStr = "bold";
            }
        } else if (fontStyle.isItalic()) {
            styleStr = "italic";
        }
        return styleStr;
    }
}

@@ -2366,32 +2366,159 @@
 Style.FontStyle 
+fontStyle;%0A            String styleStr;%0A            switch (m.getLocalName()) %7B%0A                case %22mn%22:%0A                    
 fontStyle = styl
@@ -2537,16 +2537,14 @@
 le(%22
-variable
+number
 %22);%0A
@@ -2547,38 +2547,39 @@
 %22);%0A            
-String
+       
  styleStr = getF
@@ -2606,32 +2606,40 @@
 e);%0A            
+  
+      
 if (styleStr != 
@@ -2666,43 +2666,121 @@
     
-switch (m.getLocalName()) %7B%0A       
+        m.addAttribute(new Attribute(%22mathvariant%22, styleStr));%0A                    %7D%0A                    break;%0A
     
@@ -2784,32 +2784,35 @@
             
+   
 case %22m
-n
+i
 %22:%0A         
@@ -2818,34 +2818,170 @@
             
-case %22mi%22:
+fontStyle = style.getFontStyle(%22variable%22);%0A                    styleStr = getFontStyleStr(fontStyle);%0A                    if (styleStr != null) %7B
 %0A           
@@ -3045,32 +3045,50 @@
 styleStr));%0A    
+                %7D%0A
                 
@@ -3090,36 +3090,32 @@
          break;%0A
-    
                 
@@ -3141,32 +3141,169 @@
             
-    if (
+fontStyle = style.getFontStyle(%22number%22);%0A                    styleStr = getFontStyleStr(fontStyle);%0A                    if (styleStr != null && 
 styleStr.con
@@ -3315,28 +3315,24 @@
 (%22bold%22)) %7B%0A
-    
             
@@ -3413,34 +3413,26 @@
             
-    %7D%0A    
+%7D%0A
             
@@ -3446,34 +3446,16 @@
  break;%0A
-                %7D%0A
         

handle style for number and variable separately in mathmode