--[[

TidyShop Helper class - Extends mods with features from TidyShop

Author:     w33zl
Version:    1.0
Modified:   2020-10-25

Changelog:
v1.0        Initial public release

License:    CC BY-NC-SA 4.0
This license allows reusers to distribute, remix, adapt, and build upon the material in any medium or 
format for noncommercial purposes only, and only so long as attribution is given to the creator.
If you remix, adapt, or build upon the material, you must license the modified material under identical terms. 

]]

if TidyShopHelper ~= nil then return end -- Run once

TidyShopHelper = TidyShopHelper or {}

local QueryableStoreItem = {}
QueryableStoreItem.__index = QueryableStoreItem

local function stringMatch(s1, s2)
	return (string.find(s1, s2, 1, true) ~= nil);
end--function


function TidyShopHelper:extendShopItem(shopItem)
    shopItem.tidyShop = shopItem.tidyShop or {}

    shopItem.query = shopItem.query or function(self)
        return QueryableStoreItem:new(self)
    end
end

function QueryableStoreItem:new(storeItem)
    local matchedStoreItem = {}
    setmetatable(matchedStoreItem, QueryableStoreItem);
    matchedStoreItem.storeItem = storeItem;
    matchedStoreItem.lastMatchFailed = false;
    return matchedStoreItem
end--function

function QueryableStoreItem:query()
    local matchedStoreItem = {}
    setmetatable(matchedStoreItem, QueryableStoreItem);
    matchedStoreItem.storeItem = self.storeItem;
    matchedStoreItem.lastMatchFailed = false;
    --TODO: add blacklist/exclusions
    return matchedStoreItem
end--function


function QueryableStoreItem:get()
    if self.lastMatchFailed == true then
        return nil
    else
        return self.storeItem
    end--if
end--function	

function QueryableStoreItem:matches()
    return not self.lastMatchFailed
end--function	

function QueryableStoreItem:logResult(name, result)

    self.log = (self.log or "");

    if self.log ~= "" then
        self.log = self.log .. " > ";
    end--if

    self.log = self.log .. name .. "=" .. tostring(result);
end--function


function QueryableStoreItem:debugWarning(message)
    if not DEBUG_MODE then return end

    self:debug("Warning: " .. message);
end--function

function QueryableStoreItem:debug(message)
    if not DEBUG_MODE then return end

    Mod:printDebug(message);
end--function


function QueryableStoreItem:hasName(itemName, exactMatch)

    if self.lastMatchFailed == true then
        return self;
    end--if

    local fixedStoreName = string.lower(self.storeItem.name);
    local fixedName = string.lower(itemName);

    exactMatch = (exactMatch or false) and true
    
    local function doMatch()
        if exactMatch == true then
            return fixedStoreName == fixedName
        else 
            return stringMatch(fixedStoreName, fixedName)
        end
    end
    local isMatch = doMatch()

    self.lastMatchFailed = not isMatch;

    self:logResult("hasName '" .. itemName .. "'", isMatch);

    return self;
end--function

--TODO: addSpec

--TODO: duplicate

--TODO: hasBrand

--TODO: changeBrand / newBrand

function QueryableStoreItem:isBaseGame()
    if self.lastMatchFailed == true then return self end--if

    local isMatch = (self.storeItem.customEnvironment == nil or self.storeItem.customEnvironment == "");

    self.lastMatchFailed = not isMatch;

    self:logResult("isBaseGame", isMatch);

    return self;
end--function	

function QueryableStoreItem:isMod(modName)
    if self.lastMatchFailed == true then return self end--if

    local isMatch = false;
    
    if modName ~= nil and modName ~= "" then
        if self.storeItem.customEnvironment ~= nil and self.storeItem.customEnvironment ~= "" then
            local fixedStoreModName = string.lower(self.storeItem.customEnvironment);
            local fixedModName = string.lower(modName);
            isMatch = stringMatch(fixedStoreModName, fixedModName);
        end--if
    else
        self:debugWarning("Parameter 'modName' is required!");
    end--if

    self.lastMatchFailed = not isMatch;

    self:logResult("isMod '" .. modName .. "'", isMatch);

    return self;
end--function

function QueryableStoreItem:inCategory(category)
    if self.lastMatchFailed == true then return self end--if

    local isMatch = false;
    
    if category ~= nil and category ~= "" then
        local fixedStoreCategoryName = string.upper(self.storeItem.categoryName);
        local fixedMatchCategoryName = string.upper(category);
        isMatch = (fixedStoreCategoryName == fixedMatchCategoryName);
    else
        self:debugWarning("Parameter 'category' is required!");
    end--if

    self.lastMatchFailed = not isMatch;

    self:logResult("inCategory '" .. category .. "'", isMatch);

    return self;
end--function


function QueryableStoreItem:isCategoryType(categoryType)
    if self.lastMatchFailed == true then return self end--if

    local isMatch = false;

   
    if categoryType ~= nil and categoryType ~= "" then
        local fixedStoreCategoryName = string.upper(self.storeItem.categoryName);
        local fixedMatchCategoryTypeName = string.upper(categoryType);
        
        local category = g_storeManager:getCategoryByName(fixedStoreCategoryName)

        isMatch = category ~= nil and (category.type ~= nil and category.type:upper() == fixedMatchCategoryTypeName)

        -- g_storeManager.getCategoryByName
    else
        self:debugWarning("Parameter 'categoryType' is required!");
    end--if

    self.lastMatchFailed = not isMatch;

    self:logResult("isCategoryType '" .. categoryType .. "'", isMatch);

    return self;
end--function

function QueryableStoreItem:hasFilename(filename)
    if self.lastMatchFailed == true then return self end--if

    local isMatch = false;
    
    if filename ~= nil and filename ~= "" then
        local fixedStoreFileName = string.lower(self.storeItem.xmlFilenameLower);
        local fixedMatchFileName = string.lower(filename);
        if fixedMatchFileName:sub(-4) ~= ".xml" then
            fixedMatchFileName = fixedMatchFileName .. ".xml";
        end--if
        isMatch = stringMatch(fixedStoreFileName, fixedMatchFileName);
    else
        self:debugWarning("Parameter 'filename' is required!");
    end--if

    self.lastMatchFailed = not isMatch;

    self:logResult( "hasFilename '" .. filename .. "'", isMatch);

    return self;
end--function

function QueryableStoreItem:hasSpecs(specs)
    if self.lastMatchFailed == true then return self end--if

    local isMatch = false;
    
    if specs ~= nil and specs ~= "" then
        local storeItem = self.storeItem;

        if storeItem ~= nil and storeItem.specs ~= nil and storeItem.specs.combination ~= nil then
            local fixedSpecsList = string.lower(storeItem.specs.combination);
            local fixedMatchSpecs = string.lower(specs);
            isMatch = stringMatch(fixedSpecsList, fixedMatchSpecs);
        end--if

    else
        self:debugWarning("Parameter 'specs' is required!");
    end--if

    self.lastMatchFailed = not isMatch;

    self:logResult("hasSpecs '" .. specs .. "'", isMatch);

    return self;
end--function

function QueryableStoreItem:getSpecType(specTypeName)

    local specTypePassiveIncome = g_storeManager:getSpecTypeByName(specTypeName)
    local success, passiveIncome = pcall(specTypePassiveIncome.getValueFunc, self.storeItem)

    if success then
        return passiveIncome
    else
        return nil
    end
end

function QueryableStoreItem:hasCombo(name)
    if self.lastMatchFailed == true then return self end--if

    local combination = self:getSpecType("combination")
    local isMatch = false
    
    if combination ~= nil then
        local fixedStoreComboList = string.lower(combination);
        local fixedMatchComboList = string.lower(name);
        isMatch = stringMatch(fixedStoreComboList, fixedMatchComboList);
    end

    self.lastMatchFailed = not isMatch;

    self:logResult("hasCombo", isMatch);

    return self;
end