package org.monospark.spongematchers.matcher.sponge.item;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.monospark.spongematchers.matcher.CompoundMatcher;
import org.monospark.spongematchers.matcher.SpongeMatcher;
import org.monospark.spongematchers.matcher.SpongeMatchers;
import org.spongepowered.api.data.DataQuery;
import org.spongepowered.api.data.DataView;
import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.data.meta.ItemEnchantment;
import org.spongepowered.api.item.inventory.ItemStack;

public final class ItemStackMatcher {

    private ItemStackMatcher() {}
    
    public static Builder builder() {
        return new Builder();
    }
    
    public static final class Builder {
        
        private SpongeMatcher<String> type;
        
        private SpongeMatcher<Long> damage;
        
        private SpongeMatcher<Long> amount;
        
        private SpongeMatcher<List<ItemEnchantment>> enchantments;

        private SpongeMatcher<Optional<DataView>> data;
        
        private Builder() {
            damage = SpongeMatchers.wildcard();
            amount = SpongeMatchers.wildcard();
            enchantments = SpongeMatchers.wildcard();
            data = SpongeMatchers.wildcard();
        }
        
        public Builder type(SpongeMatcher<String> type) {
            this.type = type;
            return this;
        }
        
        public SpongeMatcher<ItemStack> build() {
            return create(type, damage, amount, enchantments, data);
        }
    }
    
    public static SpongeMatcher<ItemStack> create(SpongeMatcher<String> type, SpongeMatcher<Long> damage,
            SpongeMatcher<Long> amount, SpongeMatcher<List<ItemEnchantment>> enchantments,
            SpongeMatcher<Optional<DataView>> data) {
        return CompoundMatcher.<ItemStack>builder()
                .addMatcher(type, s -> s.getItem().getId())
                .addMatcher(damage, s -> s.toContainer().getInt(DataQuery.of("UnsafeDamage")).get().longValue())
                .addMatcher(amount, s -> (long) s.getQuantity())
                .addMatcher(enchantments, s -> s.get(Keys.ITEM_ENCHANTMENTS).orElse(Collections.emptyList()))
                .addMatcher(data, s -> s.toContainer().getView(DataQuery.of("UnsafeData")))
                .build();
    }
}

@@ -802,24 +802,31 @@
 String%3E type
+Matcher
 ;%0A        %0A 
@@ -860,22 +860,29 @@
 r%3CLong%3E 
-d
 am
-age
+ountMatcher
 ;%0A      
@@ -1002,16 +1002,23 @@
 antments
+Matcher
 ;%0A%0A     
@@ -1066,16 +1066,23 @@
 w%3E%3E data
+Matcher
 ;%0A      
@@ -1124,22 +1124,29 @@
         
-d
 am
-age
+ountMatcher
  = Spong
@@ -1239,16 +1239,23 @@
 antments
+Matcher
  = Spong
@@ -1292,16 +1292,23 @@
     data
+Matcher
  = Spong
@@ -1402,16 +1402,23 @@
 ng%3E type
+Matcher
 ) %7B%0A    
@@ -1438,15 +1438,712 @@
 type
- = type
+Matcher = typeMatcher;%0A            return this;%0A        %7D%0A        %0A        public Builder damage(SpongeMatcher%3CLong%3E damageMatcher) %7B%0A            this.amountMatcher = damageMatcher;%0A            return this;%0A        %7D%0A        %0A        public Builder amount(SpongeMatcher%3CLong%3E amountMatcher) %7B%0A            this.amountMatcher = amountMatcher;%0A            return this;%0A        %7D%0A        %0A        public Builder enchantments(SpongeMatcher%3CList%3CItemEnchantment%3E%3E enchantmentsMatcher) %7B%0A            this.enchantmentsMatcher = enchantmentsMatcher;%0A            return this;%0A        %7D%0A        %0A        public Builder data(SpongeMatcher%3COptional%3CDataView%3E%3E dataMatcher) %7B%0A            this.dataMatcher = dataMatcher
 ;%0A  
@@ -2268,16 +2268,30 @@
 type
+Matcher
 , 
-d
 am
-age
+ountMatcher
 , am
@@ -2312,14 +2312,28 @@
 ents
-, data
+Matcher, dataMatcher
 );%0A 

Complete the ItemStackMatcher builder