/*
 * This File is one of the examples from Java Application Development
 * Do not reproduce this code for others or use it in a commercial setting without prior permission from the author.
 */
package salesApplication;

import datasource.DataSource;
import datasource.FileDataSource;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import products.*;
import static salesApplication.CompanyInfo.*;

/**
 *
 * @author Matthew Gregory
 * @website www.matthewgregory-author.com.au
 *
 */
public class OtherStreamingOperations {

    //data to illustrate flatMap
    static String largeText
            = "This is a large amount of text\n"
            + "It contains several lines of code\n"
            + "Each line of code contains lots of words\n"
            + "We want to process this text line by line and word by word.";
    static String[] lines = largeText.split("\n");
    static Stream<String> lineStream = Stream.of(lines);

    public static void main(String[] args) {
        DataSource ds = new FileDataSource();
        PriceList demo = ds.retrieveList("Demo");
        List<Item> demoList = demo.getList();

        //Additional Intermediate operators - peek
//        System.out.println("Discounted Notepads");
//        demoList.stream()
//                .filter(p->(p instanceof Notepad))
//                .peek(p->System.out.println("Product: "+p.getName()+" - original price "+p.getFormattedPrice()))
//                .map(clearanceSale)
//                .forEach(p->System.out.println(p));  
        //Additional Intermediate operators - flatMap
        //Print out a stream of lines one by one:
//        lineStream.forEach(line->System.out.println("line: "+line));
        //Convert the stream of lines to a stream of words
//        Stream<String> wordStream = lineStream.flatMap(line->Stream.of(line.split(" ")));
        //Print this stream word by word
//        wordStream.forEach(word->System.out.println("word: "+word));
        //Map doesn't work
//        Stream<String> wordStream = lineStream.map(line->Stream.of(line.split(" ")));
        
        //Additional Terminal Operators
        //Collect - Covert from stream back to a collection
//        List<Item> clearanceNotepadsList
//                = demoList.stream()
//                          .filter(p -> (p instanceof Notepad))
//                          .map(clearanceSale)
//                          .collect(Collectors.toList());
//        PriceList clearanceNotepads = new PriceList(clearanceNotepadsList);
//        clearanceNotepads.printList();

        //Summary Operators
        //What is the average price of my products?
//        System.out.println("Average Price: "
//                +demoList.stream().mapToDouble(p->p.getPrice()).average());
        //Result when stream is empty
//        System.out.println("Average Price: "
//                +demoList.stream().filter(p->false).mapToDouble(p->p.getPrice()).average());
        //Getting the contents from the Optional object
//        System.out.println("Average Price: "
//                +demoList.stream().mapToDouble(p->p.getPrice()).average().getAsDouble());        
        //Result when stream is empty
//        System.out.println("Average Price: "
//                +demoList.stream().filter(p->false)
//                        .mapToDouble(p->p.getPrice())
//                        .average()
//                        .getAsDouble());
        //Using sum()
//        System.out.println("Total Price: "
//            +demoList.stream().mapToDouble(p->p.getPrice()).sum());
        //count
//        System.out.println("Number of taxable items: "
//            +demoList.stream().filter(isTaxable).count());
        //max and min
        //What is the most expensive price?
//        System.out.println("Largest Price: "
//            +demoList.stream().mapToDouble(p->p.getPrice()).max());
        //What is the first product alphabetically?
//    System.out.println("First Product (Alphabetically) : "
//                            +demoList.stream()
//                            .map(p->p.getName())
//                            .min(Comparator.comparing(String::valueOf)));

        //Short-circuit terminal operators
        //Are all the Items in my demo list Products?
//        System.out.println("All Items are Products? "
//                            +demoList.stream().allMatch(p->p instanceof Product));
        //Are there any taxable items in my demo list?
//        System.out.println("All there any taxable items? "
//                            +demoList.stream().anyMatch(p->p instanceof TaxableItem));
        //No Items in my demo are more than $20?
//        System.out.println("Nothing more than $20? "
//                            +demoList.stream().noneMatch(p->p.getPrice() > 20));
        //No Items in my demo are more than $10?
//        System.out.println("Nothing more than $10? "
//                            +demoList.stream().noneMatch(p->p.getPrice() > 10));
        //Find first item that cose $20 or more
//           System.out.println("First Item $10 or more: "
//                              +demoList.stream().filter(p->p.getPrice()>=10).findFirst());

        //Find any writing implement
//        System.out.println("Any Writing Implement: "
//                            +demoList.stream().filter(p->p instanceof WritingImplement).findAny());
    }
}
