// Copyright © 2019 - 2021 Maksim Khrapov. All rights reserved.
//
// 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.



import XCTest
import pegsolitaire

final class pegsolitaireTests: XCTestCase {
    func testEnglishBoard() {
        let b = PSBoard(7, 7, 3, 3, "English", [
            0, 0, 1, 1, 1, 0, 0,
            0, 0, 1, 1, 1, 0, 0,
            1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1,
            0, 0, 1, 1, 1, 0, 0,
            0, 0, 1, 1, 1, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(121)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
        
        var foundComplement = false
        
        for i in 0..<numSolutions {
            let p1 = pruningSearch.getSolution(i)
            if p1.isComplement(p) {
                foundComplement = true
            }
        }
        
        XCTAssert(foundComplement)
    }
    
    
    func testFrenchBoard() {
        let b = PSBoard(7, 7, 2, 0, "French", [
            0, 0, 1, 1, 1, 0, 0,
            0, 1, 1, 1, 1, 1, 0,
            1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 1, 0,
            0, 0, 1, 1, 1, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
        
    }
    
    
    func test4x6Board() {
        let b = PSBoard(4, 6, 1, 1, "4x6", [
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func test6x6Board() {
        
        let b = PSBoard(6, 6, 1, 1, "6x6", [
            1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func test8x8Board() {
        
        let b = PSBoard(8, 8, 2, 1, "8x8", [
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func test9x9Board() {
        
        let b = PSBoard(9, 9, 4, 4, "9x9", [
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testCross1Board() {
        
        let b = PSBoard(5, 7, 2, 3, "Cross 1", [
            0, 1, 1, 1, 0,
            0, 1, 1, 1, 0,
            1, 1, 1, 1, 1,
            1, 1, 1, 1, 1,
            1, 1, 1, 1, 1,
            0, 1, 1, 1, 0,
            0, 1, 1, 1, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testCross2Board() {
        
        let b = PSBoard(7, 9, 3, 0, "Cross 2", [
            0, 0, 1, 1, 1, 0, 0,
            0, 0, 1, 1, 1, 0, 0,
            0, 0, 1, 1, 1, 0, 0,
            1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1,
            0, 0, 1, 1, 1, 0, 0,
            0, 0, 1, 1, 1, 0, 0,
            0, 0, 1, 1, 1, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testCross3Board() {
        
        let b = PSBoard(6, 6, 2, 3, "Cross 3", [
            0, 1, 1, 1, 0, 0,
            0, 1, 1, 1, 0, 0,
            1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1,
            0, 1, 1, 1, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testCross4Board() {
        
        
        let b = PSBoard(8, 8, 3, 4, "Cross 4", [
            0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 1, 1, 1, 0, 0, 0,
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1,
            0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 1, 1, 1, 0, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testDiamond32Board() {
        
        let b = PSBoard(7, 8, 3, 3, "Diamond 32", [
            0, 0, 0, 1, 0, 0, 0,
            0, 0, 1, 1, 1, 0, 0,
            0, 1, 1, 1, 1, 1, 0,
            1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 1, 0,
            0, 0, 1, 1, 1, 0, 0,
            0, 0, 0, 1, 0, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(100)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testDiamond41Board() {
        
        let b = PSBoard(9, 9, 3, 1, "Diamond 41", [
            0, 0, 0, 0, 1, 0, 0, 0, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 1, 1, 1, 1, 1, 0, 0,
            0, 1, 1, 1, 1, 1, 1, 1, 0,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 1, 1, 1, 0,
            0, 0, 1, 1, 1, 1, 1, 0, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 0, 0, 1, 0, 0, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(300)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testHermary39Board() {
        
        
        let b = PSBoard(7, 9, 3, 4, "Hermary 39", [
            0, 0, 0, 1, 0, 0, 0,
            0, 0, 1, 1, 1, 0, 0,
            0, 1, 1, 1, 1, 1, 0,
            1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 1, 0,
            0, 0, 1, 1, 1, 0, 0,
            0, 0, 0, 1, 0, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(350)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testHuber37Board() {
        
        let b = PSBoard(9, 9, 4, 4, "Huber 37", [
            0, 0, 0, 0, 1, 0, 0, 0, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 1, 1, 1, 1, 1, 1, 1, 0,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 1, 1, 1, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 0, 0, 1, 0, 0, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testKralenspelBoard() {
        
        
        let b = PSBoard(9, 7, 1, 1, "Kralenspel", [
            0, 1, 1, 1, 1, 1, 1, 1, 0,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            0, 1, 1, 1, 1, 1, 1, 1, 0,
            0, 0, 1, 1, 1, 1, 1, 0, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 0, 0, 1, 0, 0, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(200)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testSiege67Board() {
        
        let b = PSBoard(9, 9, 4, 0, "Siege 67", [
            0, 1, 1, 1, 1, 1, 1, 1, 0,
            0, 0, 1, 1, 1, 1, 1, 0, 0,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            0, 0, 1, 1, 1, 1, 1, 0, 0,
            0, 0, 1, 1, 1, 1, 1, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(300)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
    
    
    func testWieglebBoard() {
        
        let b = PSBoard(9, 9, 4, 4, "Wiegleb", [
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0,
            0, 0, 0, 1, 1, 1, 0, 0, 0
        ])
        
        let p = b.initialPosition()
        let pruningSearch = PSPruningSearch(p)
        pruningSearch.prune(350)
        let numSolutions = pruningSearch.search()
        XCTAssert(numSolutions > 0)
    }
}
