# ____________________________________________________________________________________
#
# 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.
# ____________________________________________________________________________________

import pickle

import pyomo.common.unittest as unittest
from pyomo.core.expr.numvalue import NumericValue
from pyomo.kernel import pprint
from pyomo.core.tests.unit.kernel.test_dict_container import (
    _TestActiveDictContainerBase,
)
from pyomo.core.tests.unit.kernel.test_tuple_container import (
    _TestActiveTupleContainerBase,
)
from pyomo.core.tests.unit.kernel.test_list_container import (
    _TestActiveListContainerBase,
)
from pyomo.core.kernel.base import ICategorizedObject
from pyomo.core.kernel.objective import (
    IObjective,
    objective,
    objective_dict,
    objective_tuple,
    objective_list,
    minimize,
    maximize,
)
from pyomo.core.kernel.variable import variable
from pyomo.core.kernel.block import block


class Test_objective(unittest.TestCase):
    def test_pprint(self):
        # Not really testing what the output is, just that
        # an error does not occur. The pprint functionality
        # is still in the early stages.
        v = variable()
        o = objective(expr=v**2)
        pprint(o)
        b = block()
        b.o = o
        pprint(o)
        pprint(b)
        m = block()
        m.b = b
        pprint(o)
        pprint(b)
        pprint(m)

    def test_ctype(self):
        o = objective()
        self.assertIs(o.ctype, IObjective)
        self.assertIs(type(o), objective)
        self.assertIs(type(o)._ctype, IObjective)

    def test_pickle(self):
        o = objective(sense=maximize, expr=1.0)
        self.assertEqual(o.sense, maximize)
        self.assertEqual(o.expr, 1.0)
        self.assertEqual(o.parent, None)
        oup = pickle.loads(pickle.dumps(o))
        self.assertEqual(oup.sense, maximize)
        self.assertEqual(oup.expr, 1.0)
        self.assertEqual(oup.parent, None)
        b = block()
        b.o = o
        self.assertIs(o.parent, b)
        bup = pickle.loads(pickle.dumps(b))
        oup = bup.o
        self.assertEqual(oup.sense, maximize)
        self.assertEqual(oup.expr, 1.0)
        self.assertIs(oup.parent, bup)

    def test_init(self):
        o = objective()
        self.assertTrue(o.parent is None)
        self.assertEqual(o.ctype, IObjective)
        self.assertEqual(o.expr, None)
        self.assertEqual(o.sense, minimize)
        self.assertEqual(o.is_minimizing(), True)

    def test_sense(self):
        o = objective()
        o.sense = maximize
        self.assertEqual(o.sense, maximize)
        self.assertEqual(o.is_minimizing(), False)
        with self.assertRaises(ValueError):
            o.sense = 100
        self.assertEqual(o.sense, maximize)
        self.assertEqual(o.is_minimizing(), False)

    def test_type(self):
        o = objective()
        self.assertTrue(isinstance(o, ICategorizedObject))
        self.assertTrue(isinstance(o, IObjective))
        self.assertTrue(isinstance(o, NumericValue))

    def test_active(self):
        o = objective()
        self.assertEqual(o.active, True)
        o.deactivate()
        self.assertEqual(o.active, False)
        o.activate()
        self.assertEqual(o.active, True)

        b = block()
        self.assertEqual(b.active, True)
        b.deactivate()
        self.assertEqual(b.active, False)
        b.o = o
        self.assertEqual(o.active, True)
        self.assertEqual(b.active, False)
        o.deactivate()
        self.assertEqual(o.active, False)
        self.assertEqual(b.active, False)
        b.activate()
        self.assertEqual(o.active, False)
        self.assertEqual(b.active, True)
        b.activate(shallow=False)
        self.assertEqual(o.active, True)
        self.assertEqual(b.active, True)
        b.deactivate(shallow=False)
        self.assertEqual(o.active, False)
        self.assertEqual(b.active, False)


class Test_objective_dict(_TestActiveDictContainerBase, unittest.TestCase):
    _container_type = objective_dict
    _ctype_factory = lambda self: objective()


class Test_objective_tuple(_TestActiveTupleContainerBase, unittest.TestCase):
    _container_type = objective_tuple
    _ctype_factory = lambda self: objective()


class Test_objective_list(_TestActiveListContainerBase, unittest.TestCase):
    _container_type = objective_list
    _ctype_factory = lambda self: objective()


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