/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 async;

import java.text.DecimalFormat;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;

public class Stockticker implements Runnable {
        public volatile boolean run = true;
        protected final AtomicInteger counter = new AtomicInteger(0);
        final List<TickListener> listeners = new CopyOnWriteArrayList<>();
        protected volatile Thread ticker = null;
        protected volatile int ticknr = 0;

        public synchronized void start() {
            run = true;
            ticker = new Thread(this);
            ticker.setName("Ticker Thread");
            ticker.start();
        }

        public synchronized void stop() {
            // On context stop this can be called multiple times.
            // NO-OP is the ticker thread is not set
            // (i.e. stop() has already completed)
            if (ticker == null) {
                return;
            }
            run = false;
            try {
                ticker.join();
            }catch (InterruptedException x) {
                Thread.interrupted();
            }

            ticker = null;
        }

        public void shutdown() {
            // Notify each listener of the shutdown. This enables them to
            // trigger any necessary clean-up.
            for (TickListener l : listeners) {
                l.shutdown();
            }
            // Wait for the thread to stop. This prevents warnings in the logs
            // that the thread is still active when the context stops.
            stop();
        }

        public void addTickListener(TickListener listener) {
            if (listeners.add(listener)) {
                if (counter.incrementAndGet()==1) start();
            }

        }

        public void removeTickListener(TickListener listener) {
            if (listeners.remove(listener)) {
                if (counter.decrementAndGet()==0) stop();
            }
        }

        @Override
        public void run() {
            try {

                Stock[] stocks = new Stock[] { new Stock("GOOG", 435.43),
                        new Stock("YHOO", 27.88), new Stock("ASF", 1015.55), };
                Random r = new Random(System.currentTimeMillis());
                while (run) {
                    for (int j = 0; j < 1; j++) {
                        int i = r.nextInt() % 3;
                        if (i < 0)
                            i = i * (-1);
                        Stock stock = stocks[i];
                        double change = r.nextDouble();
                        boolean plus = r.nextBoolean();
                        if (plus) {
                            stock.setValue(stock.getValue() + change);
                        } else {
                            stock.setValue(stock.getValue() - change);
                        }
                        stock.setCnt(++ticknr);
                        for (TickListener l : listeners) {
                            l.tick(stock);
                        }

                    }
                    Thread.sleep(850);
                }
            } catch (InterruptedException ix) {
                // Ignore
            } catch (Exception x) {
                x.printStackTrace();
            }
        }


    public static interface TickListener {
        public void tick(Stock stock);
        public void shutdown();
    }

    public static final class Stock implements Cloneable {
        protected static final DecimalFormat df = new DecimalFormat("0.00");
        protected final String symbol;
        protected double value = 0.0d;
        protected double lastchange = 0.0d;
        protected int cnt = 0;

        public Stock(String symbol, double initvalue) {
            this.symbol = symbol;
            this.value = initvalue;
        }

        public void setCnt(int c) {
            this.cnt = c;
        }

        public int getCnt() {
            return cnt;
        }

        public String getSymbol() {
            return symbol;
        }

        public double getValue() {
            return value;
        }

        public void setValue(double value) {
            double old = this.value;
            this.value = value;
            this.lastchange = value - old;
        }

        public String getValueAsString() {
            return df.format(value);
        }

        public double getLastChange() {
            return this.lastchange;
        }

        public void setLastChange(double lastchange) {
            this.lastchange = lastchange;
        }

        public String getLastChangeAsString() {
            return df.format(lastchange);
        }

        @Override
        public int hashCode() {
            return symbol.hashCode();
        }

        @Override
        public boolean equals(Object other) {
            if (other instanceof Stock) {
                return this.symbol.equals(((Stock) other).symbol);
            }

            return false;
        }

        @Override
        public String toString() {
            StringBuilder buf = new StringBuilder("STOCK#");
            buf.append(getSymbol());
            buf.append("#");
            buf.append(getValueAsString());
            buf.append("#");
            buf.append(getLastChangeAsString());
            buf.append("#");
            buf.append(String.valueOf(getCnt()));
            return buf.toString();

        }

        @Override
        public Object clone() {
            Stock s = new Stock(this.getSymbol(), this.getValue());
            s.setLastChange(this.getLastChange());
            s.setCnt(this.cnt);
            return s;
        }
    }
}
