This is a fairly standard one that's floating around the 'net.
The disadvantage with this particular implementation is that the States -> Cities are hard-wired in the code.
I started a version of this last year, which went Region (of the world, eg., Asia), then Country, then City.
About 12 million cities in total, each with latitude and longitude (this allows you to calculate the distance between two cities).
The information was, and presumably still is, freely available from a few sources in the net.
Unfortunately not all formats neatly fitted together, eg., some had ISO code for the country whilst others had the FIPS code.
Another problem was multiple entries for the same city, some with regional accents, some not.
None-the-less, with some manipulation, and patience, they can be integrated into the one DB.
Unfortunately other things took priority over this, and I didn't finish it.
The information is out there, hunt it down and have a go.