/*   Copyright 2004 The Apache Software Foundation
 *
 *   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 random.common;


import com.easypo.XmlCustomerBean;
import com.easypo.XmlLineItemBean;
import com.easypo.XmlPurchaseOrderDocumentBean.PurchaseOrder;
import com.easypo.XmlShipperBean;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.tool.CommandLine;
import org.apache.xmlbeans.impl.values.XmlValueDisconnectedException;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

public class Random implements Runnable {

    static long seed;
    static int iterations;
    static int threads;
    static int docs;


    public static void runTest(CommandLine cl) {
        if (cl.getOpt("?") != null || cl.getOpt("help") != null ||
            cl.args().length != 0) {
            System.out.println(
                "Usage: random [-seed #] [-i iterations] [-t threads] [-docs docs] [-readonly] [-nosave]");
        } else {
            boolean readonly = false;
            boolean nosave = false;
            boolean noquery = false;

            if (cl.getOpt("seed") != null) {
                seed = Long.parseLong(cl.getOpt("seed"));
            }
            if (cl.getOpt("i") != null) {
                iterations = Integer.parseInt(cl.getOpt("i"));
            }
            if (cl.getOpt("t") != null) {
                threads = Integer.parseInt(cl.getOpt("t"));
            }
            if (cl.getOpt("docs") != null) {
                docs = Integer.parseInt(cl.getOpt("docs"));
            }
            noquery = (cl.getOpt("noquery") != null);
            readonly = (cl.getOpt("readonly") != null);
            nosave = (cl.getOpt("nosave") != null);

            System.out.println("seed=" + seed);
            System.out.println("iterations=" + iterations);
            System.out.println("threads=" + threads);
            System.out.println("docs=" + docs);
            System.out.println(readonly ? "readonly" : "read/write");
            System.out.println(nosave ? "nosave" : "with save");
            System.out.println(noquery ? "noquery" : "with query");
            doTests(seed, iterations, threads, docs, readonly, nosave, noquery);
        }
    }

    private static void doTests(long seed, int iterations, int threadCount,
                                int docCount, boolean readonly, boolean nosave,
                                boolean noquery) {
        long start = System.currentTimeMillis();

        XmlObject[] sharedDocs = new XmlObject[docCount];
        Thread[] threads = new Thread[threadCount];

        for (int i = 0; i < iterations; i++) {
            for (int j = 0; j < threadCount; j++) {
                Random runnable = new Random(seed, sharedDocs, readonly,
                    nosave, noquery, threadCount > 1);
                threads[j] = new Thread(runnable);
                threads[j].start();
                seed++;
            }
            for (int j = 0; j < threadCount; j++) {
                try {
                    threads[j].join();
                } catch (InterruptedException e) {
                    System.err.println("Thread interrupted");
                }
            }
        }

        long end = System.currentTimeMillis();

        System.err.println();
        System.err.println(
            "Seconds to run random tests: " + (end - start) / 1000);
    }

    public void run() {
        System.err.print("\rSeed: " + _seed);

        try {
            for (int d = 0; d < _docs.length; d++) {
                _docs[d] = XmlObject.Factory.newInstance();
            }

            _cursors = new ArrayList<>();

            int nIterations = rnd(60000) + 5000;

            for (int i = 0; i < nIterations; i++) {
                boolean good = false;
                try {
                    _iter++;
                    iterate();
                    good = true;
                } finally {
                    if (!good) {
                        System.err.println();
                        System.err.println("Error on iteration " + _iter);
                        System.err.println();
                    }
                }
            }

            _cursors.forEach(XmlCursor::close);
            _cursors = null;
        } catch (Throwable e) {
            System.err.println("Error on seed " + _seed);
            e.printStackTrace(System.err);
        }
    }

    private java.util.Random _rnd;

    private XmlObject[] _docs; // shared among threads!!
    private ArrayList<XmlCursor> _cursors;
    private long _seed;
    private int _iter;
    private boolean _readonly;
    private boolean _nosave;
    private boolean _noquery;
    private boolean _interference;


    private int rnd(int n) {
        return _rnd.nextInt(n);
    }

    private int rnd(int min, int maxPlusOne) {
        return _rnd.nextInt(maxPlusOne - min) + min;
    }

    private XmlCursor getCursor() {
        int n = _cursors.size();

        if (n == 0 || (n < _docs.length * 3) && rnd(4) == 0) {
            XmlCursor c = _docs[rnd(_docs.length)].newCursor();
            _cursors.add(c);
            return c;
        }

        return _cursors.get(rnd(n));
    }

    private void iterate() throws Exception {
        try {
            switch (rnd(6)) {
                case 0:
                    interateHigh();
                    break;
                case 1:
                    interateHigh();
                    break;
                case 2:
                    interateHigh();
                    break;
                case 3:
                    interateMedium();
                    break;
                case 4:
                    interateMedium();
                    break;
                case 5:
                    interateLow();
                    break;
            }
        } catch (IllegalStateException e) {
            if (!_interference) {
                throw e;
            }
        } catch (IllegalArgumentException e) {
            if (!_interference) {
                throw e;
            }
        } catch (XmlValueDisconnectedException e) {

        }
    }

    private void interateHigh() throws Exception {
        switch (rnd(2)) {
            case 0:
                moveCursorRightOneToken();
                break;
            case 1:
                moveCursorLeftOneToken();
                break;
        }
    }

    private void interateMedium() throws Exception {
        switch (_readonly ? rnd(4) : rnd(24)) {
            case 0:
                getChars();
                break;
            case 1:
                getTextValue();
                break;
            case 2:
                compareValue();
                break;
            case 3:
                prevTokenType();
                break;

            case 4:
                insertText();
                break;
            case 5:
                moveCharsRight();
                break;
            case 6:
                moveCharsLeft();
                break;
            case 7:
                insertElem();
                break;
            case 8:
                insertAttr();
                break;
            case 9:
                removeXml();
                break;
            case 10:
                removeXmlContents();
                break;
            case 11:
                copyXml();
                break;
            case 12:
                copyXmlContents();
                break;
            case 13:
                moveXml();
                break;
            case 14:
                moveXmlContents();
                break;
            case 15:
                removeText();
                break;
            case 16:
                moveText();
                break;
            case 17:
                copyText();
                break;
            case 18:
                insertComment();
                break;
            case 19:
                insertProcinst();
                break;
            case 20:
                setTextValue();
                break;
            case 21:
                setStrong();
                break;
            case 22:
                objectSet();
                break;
            case 23:
                setName();
                break;
        }
    }

    private void interateLow() throws Exception {
        switch (rnd(_readonly ? 1 : 0, _nosave ? 8 : 17)) {
            case 0:
                changeType();
                break;
            case 1:
                createBookmark();
                break;
            case 2:
                clearBookmark();
                break;

            case 3:
                loadDoc();
                break;
            case 4:
                loadSchemadDoc();
                break;
            case 5:
                compareCursors();
                break;
            case 6:
                getObject();
                break;
            case 7:
                try (XmlCursor c = newCursor()) {
                }
                break;
            case 8:
                validate();
                break;
            case 9:
                execQuery();
                break;
            case 10:
                xmlStreamReader();
                break;
            case 11:
                docBytes();
                break;
            case 12:
                cursorBytes();
                break;
            case 13:
                newDomNode();
                break;
            case 14:
                objectString();
                break;
            case 15:
                cursorString();
                break;
            case 16:
                prettyObject();
                break;
        }
    }

    private XmlObject findObject() {
        XmlCursor c = getCursor();
        c.push();

        while (!(c.isContainer() || c.isAttr())) {
            if (c.toNextToken().isNone()) {
                break;
            }
        }

        if (!c.isEnddoc()) {
            XmlObject x = c.getObject();
            c.pop();
            if (x == null) {
                throw new IllegalStateException(
                    "getObject returned null - content must have changed");
            }
            return x;
        }

        c.pop();
        c.push();

        while (!(c.isContainer() || c.isAttr())) {
            if (c.toPrevToken().isNone()) {
                break;
            }
        }

        XmlObject x = c.getObject();
        c.pop();
        if (x == null) {
            throw new IllegalStateException(
                "getObject returned null - content must have changed");
        }
        return x;
    }

    private void prettyObject() {
        XmlOptions options = new XmlOptions();
        options.setSavePrettyPrint();
        findObject().xmlText(options);
    }

    private void objectString() {
        findObject().toString();
    }

    private void cursorString() {
        getCursor().toString();
    }

    private void changeType() {
        XmlObject o, n;

        try {
            o = findObject();
            SchemaType type = findObject().schemaType();
            n = o.changeType(type);
        } catch (IllegalArgumentException e) {
            return;
        } catch (IllegalStateException e) {
            return;
        }

        for (int i = 0; i < _docs.length; i++) {
            if (o == _docs[i]) {
                _docs[i] = n;
                break;
            }
        }
    }

    private void prevTokenType() {
        getCursor().prevTokenType();
    }

    private XmlCursor newCursor() {
        return findObject().newCursor();
    }

    private void setName() {
        try (XmlCursor c = newCursor()) {
            if (!c.isStartdoc()) {
                c.setName(getQName());
            }
        }
    }

    private void newDomNode() {
        if (rnd(5) != 0) {
            return;
        }

        try {
            getCursor().newDomNode();
        } catch (IllegalStateException e) {
        }
    }

    private void xmlStreamReader() throws Exception {
        if (rnd(5) != 0) {
            return;
        }

        XMLStreamReader xis;

        try {
            xis = getCursor().newXMLStreamReader();
        } catch (IllegalStateException e) {
            return;
        }

        while (xis.hasNext()) {
            xis.next();
        }
    }

    private void objectSet() {
        findObject().set(findObject());
    }

    private void setStrong() {
        XmlObject x = findObject();

        if (x instanceof PurchaseOrder) {
            PurchaseOrder o = (PurchaseOrder) x;
            o.setDate(Calendar.getInstance(TimeZone.getTimeZone(ZoneOffset.UTC), Locale.ROOT));
        } else if (x instanceof XmlCustomerBean) {
            XmlCustomerBean o = (XmlCustomerBean) x;
            o.setName("Bob");

            if (rnd(2) == 0) {
                o.setAge(23);
            }

            if (rnd(2) == 0) {
                o.setMoo(24);
            }

            if (rnd(2) == 0) {
                o.setPoo(200);
            }
        } else if (x instanceof XmlLineItemBean) {
            XmlLineItemBean o = (XmlLineItemBean) x;
            o.setPerUnitOunces(new BigDecimal(122.44));
            o.setPrice(new BigDecimal(555.33));
            o.setQuantity(BigInteger.valueOf(111));
        } else if (x instanceof XmlShipperBean) {
            XmlShipperBean o = (XmlShipperBean) x;
            o.setPerOunceRate(new BigDecimal(3.14159));
            o.setName("Eric");
        }
    }

    private void compareValue() {
        findObject().compareValue(findObject());
    }

    private void validate() {
        findObject().validate();
    }

    private void execQuery() {
        if (_noquery) {
            return;
        }

        if (rnd(20) > 0) {
            return;
        }

        QName name = getQName();

        String query =
            "declare namespace xxx='" + name.getNamespaceURI() + "' " +
            ".//xxx:" + name.getLocalPart();

        XmlObject x = getCursor().execQuery(query).getObject();

        if (rnd(3) == 0) {
            _docs[rnd(_docs.length)] = x;
        }
    }

    private void getObject() {
        getCursor().getObject();
    }

    private void getChars() {
        getCursor().getChars();
    }

    private void compareCursors() {
        try {
            getCursor().isInSameDocument(getCursor());
            getCursor().comparePosition(getCursor());
            getCursor().isAtSamePositionAs(getCursor());
        } catch (IllegalArgumentException e) {
        }
    }

    private String[] _xmls =
        {
            "<a/>",
        };

    private String[] _schema_xmls =
        {
            "<po:purchase-order xmlns:po='http://openuri.org/easypo'>\n" +
            "<po:customer age='31' poo='200'>\n" +
            "<po:name>David Bau</po:name>\n" +
            "<po:address>Gladwyne, PA</po:address>\n" +
            "</po:customer>\n" +
            "<po:customer age='37'>\n" +
            "<po:name>Eric Vasilik</po:name>\n" +
            "<po:address>Redmond, WA</po:address>\n" +
            "</po:customer>\n" +
            "<po:date>2002-09-30T14:16:00-05:00</po:date>\n" +
            "<po:line-item>\n" +
            "<po:description>Burnham's Celestial Handbook, Vol 1</po:description>\n" +
            "<po:per-unit-ounces>5</po:per-unit-ounces>\n" +
            "<po:price>21.79</po:price>\n" +
            "<po:quantity>2</po:quantity>\n" +
            "</po:line-item>\n" +
            "<po:line-item>\n" +
            "<po:description>Burnham's Celestial Handbook, Vol 2</po:description>\n" +
            "<po:per-unit-ounces>5</po:per-unit-ounces>\n" +
            "<po:price>19.89</po:price>\n" +
            "<po:quantity>2</po:quantity>\n" +
            "</po:line-item>\n" +
            "<po:line-item>\n" +
            "<po:description>Burnham's Celestial Handbook, Vol 3</po:description>\n" +
            "<po:per-unit-ounces>5</po:per-unit-ounces>\n" +
            "<po:price>19.89</po:price>\n" +
            "<po:quantity>1</po:quantity>\n" +
            "</po:line-item>\n" +
            "<po:shipper>\n" +
            "<po:name>UPS</po:name>\n" +
            "<po:per-ounce-rate>0.74</po:per-ounce-rate>\n" +
            "</po:shipper>\n" +
            "</po:purchase-order>\n" +
            "",
        };

    private void loadDoc() throws Exception {
        if (rnd(15) == 0) {
            _docs[rnd(_docs.length)] =
                XmlObject.Factory.parse(_xmls[rnd(_xmls.length)]);
        }
    }

    private void loadSchemadDoc() throws Exception {
        if (rnd(4) == 0) {
            _docs[rnd(_docs.length)] =
                XmlObject.Factory.parse(
                    _schema_xmls[rnd(_schema_xmls.length)]);
        }
    }

    private void moveCursorLeftOneToken() {
        getCursor().toPrevToken();
    }

    private void moveCursorRightOneToken() {
        getCursor().toNextToken();
    }

    private char[] _chars =
        {
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
            'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            ' ', '<', '>', '&', '-', '?'
        };

    private void getTextValue() {
        XmlCursor c = getCursor();

        if (c.isFinish() || c.isNamespace() || c.isText()) {
            return;
        }

        c.getTextValue();
    }

    private void setTextValue() {
        XmlCursor c = getCursor();

        if (c.isFinish() || c.isNamespace() || c.isText()) {
            return;
        }

        StringBuilder sb = new StringBuilder();

        for (int i = rnd(10); i >= 0; i--) {
            sb.append(_chars[rnd(_chars.length)]);
        }

        c.setTextValue(sb.toString());
    }

    private void moveText() {
        try {
            getCursor().moveChars(rnd(10), getCursor());
        } catch (IllegalArgumentException e) {
        } catch (IllegalStateException e) {
        }
    }

    private void copyText() {
        try {
            getCursor().copyChars(rnd(10), getCursor());
        } catch (IllegalArgumentException e) {
        } catch (IllegalStateException e) {
        }
    }

    private void removeText() {
        getCursor().removeChars(rnd(6));
    }

    private void insertComment() {
        try {
            getCursor().insertComment("poo");
        } catch (IllegalArgumentException e) {
        } catch (IllegalStateException e) {
        }
    }

    private void insertProcinst() {
        try {
            getCursor().insertProcInst("target", "val");
        } catch (IllegalArgumentException e) {
        } catch (IllegalStateException e) {
        }
    }

    private void insertText() {
        XmlCursor c = getCursor();

        if (c.isAnyAttr() || c.isStartdoc()) {
            return;
        }

        StringBuilder sb = new StringBuilder();

        for (int i = rnd(10); i >= 0; i--) {
            sb.append(_chars[rnd(_chars.length)]);
        }

        c.insertChars(sb.toString());
    }

    private void docChars() {
        _docs[rnd(_docs.length)].xmlText();
    }

    private void cursorChars() {
        getCursor().xmlText();
    }

    private void docBytes() throws Exception {
        _docs[rnd(_docs.length)].save(new ByteArrayOutputStream());
    }

    private void cursorBytes() throws Exception {
        getCursor().save(new ByteArrayOutputStream());
    }

    private void moveCharsRight() throws Exception {
        getCursor().toNextChar(rnd(10));
    }

    private void moveCharsLeft() throws Exception {
        getCursor().toPrevChar(rnd(10));
    }

    private QName getQName() {
        QName name = null;

        switch (rnd(3)) {
            case 0:
                name = XmlBeans.getQName("foo.com", "foo");
                break;
            case 1:
                name = XmlBeans.getQName("bar.com", "bar");
                break;
            case 2:
                name = XmlBeans.getQName("moo");
                break;
        }

        return name;
    }

    private void insertElem() throws Exception {
        XmlCursor c = getCursor();

        if (c.isAnyAttr() || c.isStartdoc()) {
            return;
        }

        c.insertElement(getQName());
    }

    public void insertAttr() {
        XmlCursor c = getCursor();

        while (!c.isEnddoc() && !c.isContainer()) {
            c.toNextToken();
        }

        if (c.isEnddoc()) {
            return;
        }

        c.toNextToken();

        c.insertAttribute(getQName());
    }

    public void removeXmlContents() {
        XmlCursor c = getCursor();

        c.removeXmlContents();
    }

    public void copyXmlContents() {
        try {
            getCursor().copyXmlContents(getCursor());
        } catch (IllegalArgumentException e) {
        } catch (IllegalStateException e) {
        }
    }

    public void copyXml() {
        try {
            getCursor().copyXml(getCursor());
        } catch (IllegalArgumentException e) {
        } catch (IllegalStateException e) {
        }
    }

    public void moveXmlContents() {
        try {
            getCursor().moveXmlContents(getCursor());
        } catch (IllegalArgumentException e) {
        } catch (IllegalStateException e) {
        }
    }

    public void moveXml() {
        try {
            getCursor().moveXml(getCursor());
        } catch (IllegalArgumentException e) {
        } catch (IllegalStateException e) {
        }
    }

    public void removeXml() {
        XmlCursor c = getCursor();

        if (!c.isStartdoc() && !c.isFinish()) {
            c.removeXml();
        }
    }

    public static class Bookmark extends XmlCursor.XmlBookmark {
    }

    public void createBookmark() throws Exception {
        getCursor().setBookmark(new Bookmark());
    }

    public void clearBookmark() throws Exception {
        getCursor().clearBookmark(Bookmark.class);
    }

    public Random(long seed, XmlObject[] sharedDocs, boolean readonly,
                  boolean nosave, boolean noquery, boolean interference) {
        _seed = seed;
        _rnd = new java.util.Random(seed);
        _docs = sharedDocs;
        _readonly = readonly;
        _nosave = nosave;
        _noquery = noquery;
        _interference = interference;
    }

}

