package ru.job4j.nonblocktask.nonblockingcache;

import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;

public class NonBlockingCacheTest {

    @Test
    public void testWith3ThreadsThenOnlyOneWrite() throws InterruptedException{
        NonBlockingCache nbc = new NonBlockingCache();
        Base first = new Base("first", 1);
        Base second = new Base("second", 2);

        nbc.add(first);
        nbc.add(second);
        nbc.add(first);

       Thread one = new Thread() {
            @Override
            public void run() {
                Base test1 = null;
                try {
                    test1 = (Base) nbc.get(1).clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                test1.edit("thread1");
                nbc.update(test1);
            }
        };

        Thread two =  new Thread() {
            @Override
            public void run() {
                try {
                    join(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Base test2 = null;
                try {
                    test2 = (Base) nbc.get(1).clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                test2.edit("thread2");
                nbc.update(test2);
            }
        };

        Thread three =  new Thread() {
            @Override
            public void run() {
                Base test3 = null;
                try {
                    test3 = (Base) nbc.get(1).clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                test3.edit("thread3");
                nbc.update(test3);
            }
        };

        Thread four =  new Thread() {
            @Override
            public void run() {
                try {
                    join(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Base test4 = null;
                try {
                    test4 = (Base) nbc.get(1).clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                test4.edit("thread4");
                nbc.update(test4);
            }
        };


        one.start();
        two.start();
        three.start();
        four.start();
        one.join();
        two.join();
        three.join();
        four.join();

        assertThat(nbc.get(1).getName(), is("thread4"));


    }

    @Test(expected = OptimisticException.class)
    public void testWithoutThreads() throws CloneNotSupportedException {
        NonBlockingCache nbc = new NonBlockingCache();
        Base originModel = new Base("first", 1);
        nbc.add(originModel);

        Base changeModel = (Base) nbc.get(1).clone();
        Base changeModelTwo = (Base) nbc.get(1).clone();
        changeModel.edit("v2");
        nbc.update(changeModel);
        changeModelTwo.edit("v2 again");
        nbc.update(changeModelTwo);
    }

    @Test
    public void TestWhenDeleteValue() {
        NonBlockingCache nbc = new NonBlockingCache();
        Base first = new Base("first", 1);
        Base second = new Base("second", 2);

        nbc.add(first);
        nbc.add(second);
        nbc.delete(first);

        assertThat(null, is(nbc.get(1)));

    }

}