# ____________________________________________________________________________________
#
# Pyomo: Python Optimization Modeling Objects
# Copyright (c) 2008-2026 National Technology and Engineering Solutions of Sandia, LLC
# Under the terms of Contract DE-NA0003525 with National Technology and Engineering
# Solutions of Sandia, LLC, the U.S. Government retains certain rights in this
# software.  This software is distributed under the 3-clause BSD License.
# ____________________________________________________________________________________
#
# Unit Tests for pyomo.opt.base.convert
#

import os
from os.path import abspath, dirname

pyomodir = dirname(abspath(__file__)) + os.sep + ".." + os.sep + ".." + os.sep
currdir = dirname(abspath(__file__)) + os.sep

import pyomo.common.unittest as unittest

from pyomo.common.errors import ApplicationError
from pyomo.common.tempfiles import TempfileManager

import pyomo.opt

old_tempdir = TempfileManager.tempdir


class MockArg:
    def __init__(self):
        pass

    def valid_problem_types(self):
        return [pyomo.opt.ProblemFormat.pyomo]

    def write(self, filename="", format=None):
        pass


class MockArg2(MockArg):
    def valid_problem_types(self):
        return [pyomo.opt.ProblemFormat.nl]

    def write(self, filename="", format=None):
        OUTPUT = open(filename, "w")
        INPUT = open(currdir + "test4.nl")
        for line in INPUT:
            print >> OUTPUT, line,
        OUTPUT.close()
        INPUT.close()


class MockArg3(MockArg):
    def valid_problem_types(self):
        return [pyomo.opt.ProblemFormat.mod]

    def write(self, filename="", format=None):
        pass


class MockArg4(MockArg):
    def write(self, filename="", format=None):
        OUTPUT = open(filename, "w")
        INPUT = open(currdir + "test4.nl")
        for line in INPUT:
            print >> OUTPUT, line,
        OUTPUT.close()
        INPUT.close()


class OptConvertDebug(unittest.TestCase):
    def setUp(self):
        TempfileManager.push()
        TempfileManager.tempdir = currdir

    def tearDown(self):
        TempfileManager.clear_tempfiles()
        TempfileManager.tempdir = old_tempdir

    def test_nl_nl1(self):
        """Convert from NL to NL"""
        ans = pyomo.opt.convert_problem(
            ("test4.nl",), None, [pyomo.opt.ProblemFormat.nl]
        )
        self.assertEqual(ans[0], ("test4.nl",))

    def test_nl_nl2(self):
        """Convert from NL to NL"""
        ans = pyomo.opt.convert_problem(
            ("test4.nl", "tmp.nl"), None, [pyomo.opt.ProblemFormat.nl]
        )
        self.assertEqual(ans[0], ("test4.nl", "tmp.nl"))

    def test_error1(self):
        """No valid problem types"""
        try:
            pyomo.opt.convert_problem(
                ("test4.nl", "tmp.nl"), pyomo.opt.ProblemFormat.nl, []
            )
            self.fail("Expected pyomo.opt.ConverterError exception")
        except pyomo.opt.ConverterError:
            pass

    def test_error2(self):
        """Target problem type is not valid"""
        try:
            pyomo.opt.convert_problem(
                ("test4.nl", "tmp.nl"),
                pyomo.opt.ProblemFormat.nl,
                [pyomo.opt.ProblemFormat.mps],
            )
            self.fail("Expected pyomo.opt.ConverterError exception")
        except pyomo.opt.ConverterError:
            pass

    def test_error3(self):
        """Empty argument list"""
        try:
            pyomo.opt.convert_problem((), None, [pyomo.opt.ProblemFormat.mps])
            self.fail("Expected pyomo.opt.ConverterError exception")
        except pyomo.opt.ConverterError:
            pass

    def test_error4(self):
        """Unknown source type"""
        try:
            pyomo.opt.convert_problem(
                ("prob.foo",), None, [pyomo.opt.ProblemFormat.mps]
            )
            self.fail("Expected pyomo.opt.ConverterError exception")
        except pyomo.opt.ConverterError:
            pass

    def test_error5(self):
        """Unknown source type"""
        try:
            pyomo.opt.convert_problem(
                ("prob.lp",), pyomo.opt.ProblemFormat.nl, [pyomo.opt.ProblemFormat.nl]
            )
            self.fail("Expected pyomo.opt.ConverterError exception")
        except pyomo.opt.ConverterError:
            pass

    def test_error6(self):
        """Cannot use pico_convert with more than one file"""
        try:
            ans = pyomo.opt.convert_problem(
                (currdir + "test4.nl", "foo"), None, [pyomo.opt.ProblemFormat.cpxlp]
            )
            self.fail("Expected pyomo.opt.ConverterError exception")
        except pyomo.opt.ConverterError:
            pass

    def test_error8(self):
        """Error when source file cannot be found"""
        try:
            ans = pyomo.opt.convert_problem(
                (currdir + "unknown.nl",), None, [pyomo.opt.ProblemFormat.cpxlp]
            )
            self.fail("Expected pyomo.opt.ConverterError exception")
        except ApplicationError:
            if pyomo.common.Executable("pico_convert"):
                self.fail(
                    "Expected ApplicationError because pico_convert is not available"
                )
            return
        except pyomo.opt.ConverterError:
            pass

    def test_error9(self):
        """The Opt configuration has not been initialized"""
        cmd = pyomo.common.Executable("pico_convert")
        if cmd:
            cmd.disable()
        try:
            ans = pyomo.opt.convert_problem(
                (currdir + "test4.nl",), None, [pyomo.opt.ProblemFormat.cpxlp]
            )
            self.fail("This test didn't fail, but pico_convert should not be defined.")
        except pyomo.opt.ConverterError:
            pass
        cmd.rehash()

    def test_error10(self):
        """GLPSOL can only convert file data"""
        try:
            arg = MockArg3()
            ans = pyomo.opt.convert_problem(
                (arg, pyomo.opt.ProblemFormat.cpxlp, arg),
                None,
                [pyomo.opt.ProblemFormat.cpxlp],
            )
            self.fail("This test didn't fail, but glpsol cannot handle objects.")
        except pyomo.opt.ConverterError:
            pass

    def test_error11(self):
        """Cannot convert MOD that contains data"""
        try:
            ans = pyomo.opt.convert_problem(
                (currdir + "test3.mod", currdir + "test5.dat"),
                None,
                [pyomo.opt.ProblemFormat.cpxlp],
            )
            self.fail(
                "Expected pyomo.opt.ConverterError exception because we provided a MOD file with a 'data;' declaration"
            )
        except ApplicationError:
            if pyomo.common.Executable("glpsol"):
                self.fail("Expected ApplicationError because glpsol is not available")
            return
        except pyomo.opt.ConverterError:
            pass


if __name__ == "__main__":
    unittest.main()
