// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 Longest Valid Parentheses Solution
//
// Licensed 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.

#include "LongestValidParentheses.h"

int LongestValidParentheses::FindLongestValidDp(const std::string& s) {
    if (!IsValidInput(s) || s.length() < 2) {
        return 0;
    }
    
    int string_len = static_cast<int>(s.length());
    std::vector<int> dp(string_len, 0);
    int max_length = 0;
    
    // dp[i] represents the length of longest valid parentheses ending at index i
    for (int i = 1; i < string_len; ++i) {
        if (s[i] == ')') {
            if (s[i - 1] == '(') {
                // Case: ...()
                dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
            } else if (dp[i - 1] > 0) {
                // Case: ...))
                int matching_index = i - dp[i - 1] - 1;
                if (matching_index >= 0 && s[matching_index] == '(') {
                    dp[i] = dp[i - 1] + 2 + (matching_index > 0 ? dp[matching_index - 1] : 0);
                }
            }
            max_length = std::max(max_length, dp[i]);
        }
    }
    
    return max_length;
}

int LongestValidParentheses::FindLongestValidStack(const std::string& s) {
    if (!IsValidInput(s) || s.length() < 2) {
        return 0;
    }
    
    std::stack<int> index_stack;
    index_stack.push(-1); // Base for length calculation
    int max_length = 0;
    
    for (int i = 0; i < static_cast<int>(s.length()); ++i) {
        if (s[i] == '(') {
            index_stack.push(i);
        } else { // s[i] == ')'
            index_stack.pop();
            
            if (index_stack.empty()) {
                // No matching '(' found, push current index as new base
                index_stack.push(i);
            } else {
                // Calculate length of current valid parentheses
                int current_length = i - index_stack.top();
                max_length = std::max(max_length, current_length);
            }
        }
    }
    
    return max_length;
}

int LongestValidParentheses::FindLongestValidTwoPass(const std::string& s) {
    if (!IsValidInput(s) || s.length() < 2) {
        return 0;
    }
    
    int left_cnt = 0;
    int right_cnt = 0;
    int max_length = 0;
    int string_len = static_cast<int>(s.length());
    
    // Left to right pass
    for (int i = 0; i < string_len; ++i) {
        if (s[i] == '(') {
            ++left_cnt;
        } else {
            ++right_cnt;
        }
        
        if (left_cnt == right_cnt) {
            max_length = std::max(max_length, 2 * right_cnt);
        } else if (right_cnt > left_cnt) {
            left_cnt = right_cnt = 0;
        }
    }
    
    // Right to left pass
    left_cnt = right_cnt = 0;
    for (int i = string_len - 1; i >= 0; --i) {
        if (s[i] == '(') {
            ++left_cnt;
        } else {
            ++right_cnt;
        }
        
        if (left_cnt == right_cnt) {
            max_length = std::max(max_length, 2 * left_cnt);
        } else if (left_cnt > right_cnt) {
            left_cnt = right_cnt = 0;
        }
    }
    
    return max_length;
}

int LongestValidParentheses::FindLongestValid(const std::string& s) {
    // Use the most space-efficient approach as default
    return FindLongestValidTwoPass(s);
}

bool LongestValidParentheses::IsValidInput(const std::string& s) const {
    for (char c : s) {
        if (c != '(' && c != ')') {
            return false;
        }
    }
    return true;
}